2012-09-24 2 views
10

왜 소멸자가 생성자보다 더 자주 호출되는 것처럼 보입니까?

#include<iostream> 
using namespace std; 

class A{ 
public: 
    static int cnt; 
    A() 
    { 
     ++cnt; 
     cout<<"constructor:"<<cnt<<endl; 
    } 
    ~A() 
    { 
     --cnt; 
     cout<<"destructor:"<<cnt<<endl; 
    } 
}; 

int A::cnt = 0; 

A f(A x){ 
    return x; 
} 
int main(){ 
    A a0; 
    A a1 = f(a0); 
    return 0; 
} 
프로그램 출력됩니다 :

 
constructor:1 
destructor:0 
destructor:-1 
destructor:-2 

생성자와 소멸자가 쌍으로 표시되지 않는 이유는 무엇입니까?

+0

스택 오버플로에 오신 것을 환영합니다! +1 및 전체 샘플 프로그램을 제공해 주셔서 감사합니다. 왜 그것이 중요한지 http://SSCCE.ORG를 참조하십시오. –

+1

'return x;'에 의해 호출 된 복사 생성자는 분명히 이미 최적화되어 있지만 충분히 공격적인 옵티마이 저는'f' ('x'가 값으로 전달됨) 호출시 호출을 제거 할 수 있을지 궁금합니다. 그래서 효과적으로 한 번 기본 소멸자를 호출 한 다음 복사 생성자를 호출합니다. –

+1

@FrerichRaabe : 최적화는 특정 상황에서만 복사 생성자 추출을 허용하는 표준을 따르지 않습니다. 허용 된 모든 상황에서, 생략 된 사본의 출처 또는 목적지가 일시적입니다. –

답변

14

카운터를 늘리는 복사 생성자를 추가해야합니다. 당신이 명시 적으로 추가하지 않으면

A(const A&) 
{ 
    ++cnt; 
    cout<<"copy constructor:"<<cnt<<endl; 
} 

컴파일러는 카운터 cnt으로 아무것도하지 않는 하나를 생성합니다.

이 표현

A a1 = f(a0); 

하면 복사 생성자를 사용합니다 a0의 복사본을 만드는 것입니다. 정확한 복사 매수는 copy elision에 따라 다를 수 있지만 프로그램 끝에서 은 0이어야합니다.

: 당신이 당신의 자신의 복사 생성자를 선언하면 C++ 11에서, 당신은 또한 이동 복사 생성자 생성 된 컴파일러의 가능성을 고려해야하지만, 컴파일러는 더 이상 이동 버전을 생성하지 않습니다.

3

복사 생성자 호출도 계산해야합니다. C++ 11에는 이동 생성자도 고려해야합니다.

5

모든 생성자를 추적하지 않으며 기본 생성자 만 추적합니다. 컴파일러는 복사 생성자를 생성하고 두 번 사용하여 파괴 된 것으로 나열된 객체와 생성되지 않은 객체 2 개를 계산합니다.

관련 문제