복사 엘리션 복사
Copy elisionC++ 컴퓨터 프로그래밍에서 copy elision은 객체의 불필요한 복사를 제거하는 컴파일러 최적화 기술을 말합니다.
C++ 언어 표준은 결과 프로그램의 관찰 가능한 동작이 표준에서 명령한 대로 정확히 실행되었다고 가정하는 것과 동일하다면 일반적으로 구현이 모든 최적화를 수행할 수 있도록 합니다.게다가 이 규격에서는, 프로그램의 동작이 변경되어도 카피가 불필요하게 되는 몇개의 상황도 기술하고 있습니다.가장 일반적인 것은 반환값 최적화입니다(아래 참조).C++ 표준에서 설명하는 또 다른 널리 구현되는 최적화는 클래스 유형의 임시 개체가 동일한 [1]유형의 개체에 복사되는 경우입니다.그 결과, 카피 초기화는 통상, 퍼포먼스 면에서는 직접 초기화와 동등하지만, 의미론 면에서는 그렇지 않습니다.카피 초기화에는 액세스 가능한 카피 [2]컨스트럭터가 필요합니다.최적화는 참조에 바인딩된 임시 개체에는 적용할 수 없습니다.
예
#실패하다 <iostream> 인트 n = 0; 구조 C { 명시적 C(인트) {} C(컨스턴트 C&) { ++n; } // 복사 생성자에 눈에 보이는 부작용이 있습니다. }; // 정적 저장 기간을 사용하여 개체를 수정합니다. 인트 주된() { C c1(42); // 직접 초기화, C::C(int) 호출 C c2 = C(42); // 복사 초기화, C::C(const C&) 호출 표준::외치다 << > n << > 표준::끝; // 복사가 생략된 경우 0, 그렇지 않은 경우 1 인쇄 }
이 규격에 따르면 던지고 [3][4]잡히는 오브젝트에 대해서도 같은 최적화를 적용할 수 있지만, 그 최적화가 던져진 오브젝트에서 예외 오브젝트로의 복사와 catch 절의 예외 선언에서 선언된 오브젝트로의 복사 모두에 적용되는지 여부는 불명확하다.또한 이 최적화가 임시 개체에만 적용되는지 아니면 명명된 개체에도 [5]적용되는지도 불분명합니다.소스코드는 다음과 같습니다.
#실패하다 <iostream> 구조 C { C() = 체납; C(컨스턴트 C&) { 표준::외치다 << > 헬로 월드!\n"; } }; 무효 f() { C c; 던지다 c; // 이름 있는 개체 c를 예외 개체로 복사합니다. } // 이 복사본을 생략할 수 있는지(제외) 불분명합니다. 인트 주된() { 해라 { f(); } 또 만나 (C c) { // 예외 오브젝트를 의 임시로 복사합니다. // 예외 선언. } // 이 복사본을 생략할 수 있는지도 불분명합니다. }
따라서 컴파일러에 적합한 경우 "Hello World!"를 두 번 인쇄하는 프로그램을 생성해야 합니다.C++ 표준(C++11)의 현재의 리비전에서는, 이 문제에 대처하고 있습니다.기본적으로 이름 있는 오브젝트에서 예외 오브젝트로의 카피와 예외 핸들러로 선언된 오브젝트로의 카피는 모두 [5]생략할 수 있습니다.
GCC가 제공하는 것은-fno-elide-constructors
옵션을 지정하여 복사 삭제를 비활성화합니다.이 옵션은 복사가 생략된 반환값 최적화 또는 기타 최적화의 효과를 관찰(또는 관찰하지 않음)하는 데 유용합니다.일반적으로 이 중요한 최적화를 디세블로 하는 것은 권장되지 않습니다.
반환값 최적화
C++ 프로그래밍 언어에서 RVO(Return Value Optimization)는 함수의 반환값을 [6]유지하기 위해 생성된 임시 객체를 제거하는 컴파일러 최적화입니다.RVO는 C++ [7]표준에 따라 결과 프로그램의 관찰 가능한 동작을 변경할 수 있습니다.
요약
일반적으로 C++ 표준은 결과 실행 파일이 표준의 모든 요건이 충족된 것처럼 관찰 가능한 동일한 동작을 보인다면 컴파일러가 모든 최적화를 수행할 수 있도록 한다.이를 일반적으로 "as-if 규칙"[8]이라고 합니다.반환값 최적화라는 용어는 C++ 표준에서 "as-if" 규칙보다 훨씬 더 나아가는 특별한 절을 말합니다. 즉, 구현은 복사 컨스트럭터의 부작용이 [1]있더라도 반환문에 기인하는 복사 작업을 생략할 수 있습니다.
다음의 예는, 카피 컨스트럭터가 눈에 보이는 부작용(텍스트의 인쇄)[1]이 있는 경우에서도, 실장시에 의해서 작성되고 있는 카피 중 하나 또는 양쪽이 삭제되는 시나리오를 나타내고 있습니다.삭제할 수 있는 첫 번째 복사본은 이름 없는 임시 복사본입니다.C
함수에 복사할 수 있습니다.f
의 반환값.삭제할 수 있는 두 번째 복사본은 에 의해 반환된 임시 객체의 복사본입니다.f
로.obj
.
#실패하다 <iostream> 구조 C { C() = 체납; C(컨스턴트 C&) { 표준::외치다 << > "복사가 되었습니다.\n"; } }; C f() { 돌아가다 C(); } 인트 주된() { 표준::외치다 << > 헬로 월드!\n"; C obj = f(); }
컴파일러와 그 컴파일러의 설정에 따라서는, 다음의 몇개의 출력이 표시되는 경우가 있습니다.
헬로 월드!복사가 되었다.복사가 되었다.
헬로 월드!복사가 되었다.
헬로 월드!
배경
함수에서 빌트인 타입의 오브젝트를 반환하는 경우 오브젝트는 일반적으로 CPU 레지스터에 들어가므로 오버헤드가 거의 발생하지 않습니다.클래스 타입의 큰 오브젝트를 되돌리는 경우는, 메모리 위치간에 카피하는 비용이 드는 일이 있습니다.이를 피하기 위해 구현에서는 발신자의 스택프레임 내에 숨겨진 오브젝트를 생성하여 이 오브젝트의 주소를 함수에 전달할 수 있습니다.그런 다음 함수의 반환 값이 숨겨진 [9]개체로 복사됩니다.따라서 다음과 같은 코드가 있습니다.
구조 데이터. { 차 바이트 수[16]; }; 데이터. F() { 데이터. 결과 = {}; // 결과 생성 돌아가다 결과; } 인트 주된() { 데이터. d = F(); }
는 다음과 같은 코드를 생성할 수 있습니다.
구조 데이터. { 차 바이트 수[16]; }; 데이터.* F(데이터.* _hidden Address(숨겨진 주소)) { 데이터. 결과 = {}; // 결과를 숨김 객체에 복사 *_hidden Address(숨겨진 주소) = 결과; 돌아가다 _hidden Address(숨겨진 주소); } 인트 주된() { 데이터. 숨김; // 숨김 개체 만들기 데이터. d = *F(&숨김); // 결과를 d에 복사합니다. }
이로 인해Data
두 번 복사할 객체입니다.
C++의 진화 초기 단계에서는 함수에서 클래스 유형의 객체를 효율적으로 반환할 수 없는 것이 [10]약점으로 여겨졌다.1991년경 Walter Bright는 복사를 최소화하는 기술을 구현하여 함수의 숨겨진 객체와 명명된 객체를 결과를 [11]유지하는 데 사용되는 객체로 효과적으로 대체했습니다.
구조 데이터. { 차 바이트 수[16]; }; 무효 F(데이터.* p) { // *p에서 직접 결과 생성 } 인트 주된() { 데이터. d; F(&d); }
Bright는 Zortech C++ [10]컴파일러에 이 최적화를 실장했습니다.이 특정 기술은 나중에 명명된 객체의 복사가 [11]생략된다는 사실을 언급하여 "이름 있는 반환값 최적화"(NRVO)라는 이름으로 만들어졌습니다.
컴파일러 지원
반환값 최적화는 대부분의 [6][12][13]컴파일러에서 지원됩니다.그러나 컴파일러가 최적화를 수행할 수 없는 상황이 발생할 수 있습니다.일반적인 [9][12][14]예로는 함수가 실행 경로에 따라 다른 이름 있는 개체를 반환하는 경우가 있습니다.
#실패하다 <문자열> 표준::스트링 F(부울 견디다 = 거짓의) { 표준::스트링 첫번째("처음"); 표준::스트링 둘째("초"); // 함수가 두 개의 명명된 개체 중 하나를 반환할 수 있습니다. // 인수에 따라 달라집니다.RVO가 적용되지 않을 수 있습니다. 돌아가다 견디다 ? 첫번째 : 둘째; } 인트 주된() { 표준::스트링 결과 = F(); }
외부 링크
레퍼런스
- ^ a b c ISO/IEC(2003)ISO/IEC 14882:2003(E): 프로그래밍 언어 - C++ © 12.8 클래스 객체 복사 [class.copy] para.15
- ^ Sutter, Herb (2001). More Exceptional C++. Addison-Wesley.
- ^ ISO/IEC(2003)ISO/IEC 14882:2003(E): 프로그래밍 언어 - C++ © 15.1 예외 발생 [예외]던지다5
- ^ ISO/IEC(2003)ISO/IEC 14882:2003(E): 프로그래밍 언어 - C++ © 15.3 예외 처리 [except.handle] para.17 .
- ^ a b "C++ Standard Core Language Defect Reports". WG21. Retrieved 2009-03-27.
- ^ a b Meyers, Scott (1995). More Effective C++. Addison-Wesley. ISBN 9780201633719.
- ^ Alexandrescu, Andrei (2003-02-01). "Move Constructors". Dr. Dobb's Journal. Retrieved 2009-03-25.
- ^ ISO/IEC(2003)ISO/IEC 14882:2003(E): 프로그래밍 언어 - C++ © 1.9 프로그램 실행 [intro.execution]파라.1
- ^ a b Bulka, Dov; David Mayhew (2000). Efficient C++. Addison-Wesley. ISBN 0-201-37950-3.
- ^ a b Lippman, Stan (2004-02-03). "The Name Return Value Optimization". Microsoft. Retrieved 2009-03-23.
- ^ a b "Glossary D Programming Language 2.0". Digital Mars. Retrieved 2009-03-23.
- ^ a b Shoukry, Ayman B. (October 2005). "Named Return Value Optimization in Visual C++ 2005". Microsoft. Retrieved 2009-03-20.
- ^ "Options Controlling C++ Dialect". GCC. 2001-03-17. Retrieved 2018-01-20.
- ^ Hinnant, Howard; et al. (2002-09-10). "N1377: A Proposal to Add Move Semantics Support to the C++ Language". WG21. Retrieved 2009-03-25.