2012-10-14 3 views
0

다음 코드는 A::A() 만 인쇄하고 A::A(const A&) 또는 operator=은 인쇄하지 않습니다. 왜?반환 값으로 인해 개체가 복사되지 않는 이유는 무엇입니까?

struct A 
{ 
    A()    { cout << "A::A()" << endl; } 
    A(const A& value) { cout << "A::A(const A&)" << endl; } 

    A& operator=(const A& newValut) 
    { 
    cout << "A::operator=" << endl; 
    return *this; 
    } 
}; 

A foo() 
{ 
    A a;  //Ok, there we have to create local object by calling A::A(). 
    return a; //And there we need to copy it, otherwise it will be destroyed 
      //because it's local object. But we don't. 
} 

int main() 
{ 
    A aa = foo(); //Also there we need to put result to the aa 
        //by calling A::A(const A&), but we don't. 
} 

그래서이 코드는

A::A() 
A::A(const A&) 
A::A(const A&) 

를 인쇄해야하지만 그렇지 않습니다. 왜?

foo()의 인라이닝이 최적화되지 않은 경우 g++에없는 것이 좋습니다.

답변

10

이것을 "Return Value Optimization"이라고합니다. 컴파일러는 이와 같은 경우에 복사본을 삭제할 수 있습니다.

3

이것은 복잡한 유형의 반환이 C++에서 수행되는 방법입니다. 반환 된 객체의 위치는 함수를 호출하기 전에 실제로 호출자가 제공하며이 초기화되지 않은 객체에 대한 포인터는 숨겨진 인수로 전달됩니다 함수에. 이 함수는이 메모리 위치를 사용하여 반환 된 표현식에서 반환 된 객체를 생성합니다.

따라서 반환 된 객체가 프로그램 A aa = foo();과 같이 새 객체를 직접 초기화하는 경우 반환 된 값을 스택의 객체에 복사 할 필요가 없습니다. 함수가이 위치에 직접 객체를 생성하도록 요청합니다. 따라서 복사 생성자에게 한 번만 호출하면됩니다. (실제로 복사 생성자에 대한 호출이 2 번이라면 C++ 컴파일러는 호환되지 않습니다.

이제 컴파일러는 "반환 값 최적화"또는 RVO라는 최적화에서이 호출을 최적화 할 수 있습니다. 어떻게 가능합니까? 코드를 살펴보면 반환 값의 제안 된 위치에서 foo()의 로컬 "a"변수를 직접 정의 할 수 있으므로 다시 복사 할 필요가 없음을 알 수 있습니다. 복사 생성자가 복잡하고 느리게 실행될 수 있으므로 구현시 (그리고 모든 컴파일러에서이 기능을 구현할 때) 성능을 크게 향상시킬 수 있기 때문에 이것은 중요한 기능입니다.

따라서 귀하의 경우 컴파일러에 따라 복사 생성자에 대한 호출이 1 개 또는 0 개일 수 있으며 컴파일러는 여전히 호환됩니다.