2016-08-24 6 views
1

내 프로그램이 예상치 못한 방식으로 작동하는 이유를 혼란스러워했습니다. 그런 다음이 단순화 된 버전을 작성하여 "누락 된"생성자 호출이 있음을 발견했습니다.누락 된 생성자 호출

template <class T> 
class A 
{ 
public: 

    A() {std::cout << "default" << "\n";} // default ctor 

    A (const A& src)      // copy ctor 
    { 
     std::cout << "copy" << "\n"; 
    } 

    friend A<T> operator<<(A& a, unsigned i) 
    { 
     std::cout << "x1" << "\n"; 
     A tmp; 
     std::cout << "x2" << "\n"; 
     return tmp; 
    } 
}; 


int main() 
{ 
    A<int> a1; 
    A<int> a2(a1 << 2); 
} 

내가 기대했던 어떤 출력

default 
x1 
default 
x2 

a1 << 2에 의해 반환 된 r 값으로

default 
x1 
default 
x2 
copy 

가 복사 ctor에의 const A& 매개 변수로 전달 될 수 있었다. 그러나 그것은 어떻게되지 않습니다. 그렇지 않으면 내가 a2의 생성자를 호출 할 필요가 있다는 생각 때문에 그리고 그 후 적어도 나는

default 
x1 
default 
x2 
default 

을 기대.

여기에 무슨 일이 일어나고 있습니까?

+1

복사. 나는 최적화없이 컴파일해야한다고 생각한다. – Rakete1111

+1

나는 그것에 대해 읽었지만 나에게도 여전히 3 가지 기본 호출을 사용하는 변형이 왜 그런지 설명하지 못했습니다. –

+0

그리고 어쨌든 최적화로 컴파일하고 있지 않습니다. –

답변

2

복사 elision입니다. 구체적으로는, N 는 아메드 R은 V ALUE O ptimization 또는 NRVO을 eturn.

NRVO 자동 저장 기간과 변수 (함수에) 지역 함수로부터 값으로 복귀 될 때 발생하고, 그 값은 변수에 할당된다 컴파일러는을 생략하다시킨다

friend A<T> operator<<(A& a, unsigned i) 
{ 
    //... 
    A tmp; //automatic storage variable 
    //... 
    return tmp; //returned by value 
} 

A<int> a2(a1 << 2); //Assigned to a2 

tmp ~ a2 사본 이것은 기본적으로 함수가 끝날 때 tmp의 메모리가 할당 해제되지 않는다는 것을 의미합니다! 그런 다음 을 해당 메모리 위치에 할당하면 기본적으로 "복사"는 tmp이됩니다.

복사/이동 생성자 및 소멸자조차도 일부 값 출력과 같은 부작용이있을 때 발생합니다. 그러나 이것이 구현 정의되어 있기 때문에 일부 컴파일러는 두 번째 및/또는 세 번째 경우를 출력 할 수도 있습니다.

다른 형태의 복사 제거에 대해서는 those answers을 참조하십시오.