2016-09-13 1 views
2

이 코드는 다음과 같습니다왜 이런 상황에서는 하나의 생성자 만 호출되지만 두 개의 소멸자가 호출됩니다. 처음에

#include "stdafx.h" 
#include<iostream> 
using namespace std; 

class Test{ 
public: 
    explicit Test(int); 
    ~Test(); 
    //Test(Test&); 
    int varInt; 
}; 
Test::Test(int temp){ 
    varInt = temp; 
    cout << "call Test::constructor\n"; 
} 
Test::~Test(){ 
    cout << "call Test::destructor\n"; 
} 
/*Test::Test(Test&temp){ 
    varInt = temp.varInt; 
    cout << "call Test::copy constructor\n"; 
}*/ 
void func(Test temp){ 
    cout << "call func\n"; 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    func(Test(1)); 
    return 0; 
} 

출력 :

call Test::constructor 
call func 
call Test::destructor 
call Test::destructor 

이 (FUNC의 인수로) 생성 된 하나의 개체 만있을 원인, 나에게 혼란 만 함수가 끝난 후에 두 소멸자가 호출되었습니다. 기본 복사 생성자가 호출 되었기 때문에 이것이 궁금한가요? 그래서 복사 생성자에 대한 정의를 작성했습니다. 복사 생성자의 정의가 작성되어 좀 더 이상해졌습니다.

가 출력 :

call Test::constructor 
call func 
call Test::destructor 

상황이 지금 단지되었다 당신은 클래스로, 위의 복사 생성자, 즉 정의를 볼 수 내가 주석 처리 된 코드를 추가 한 후 는, 출력은 다음과 같이되었다 . 누군가이 현상을 나에게 설명 할 수 있습니까? 대단히 감사합니다.

+1

복사/이동 생성자를 잊어 버렸습니다. – Rakete1111

+1

복사 생성자를 만들지 않으면 컴파일러에서 자체 생성자를 만듭니다. –

답변

3
  • 원래 코드에 대한 해석 (암시 적으로 선언 된 복사본 생성자가 호출 됨)이 정확합니다.
    • 컴파일러에서 구현하는 표준 버전에 따라 암시 적으로 선언 된 이동 생성자가 실제로 사용 중일 수 있습니다. 그러나 이것은 같은 양입니다. (명시 적으로 복사 생성자를 제공 한)
  • 귀하의 수정 된 코드는 컴파일러가 바로 시작하기 원하는 위치에 객체를 구성 the copy elision optimization을 유발하는 발생합니다. 이것은 표준이 프로그램의 관찰 가능한 동작에 영향을 미치더라도 최적화를 허용하는 몇 가지 상황 중 하나입니다 (복사 생성자가 호출되었는지 여부를 알 수 있으므로).
  • 수정 된 코드에 관한 정보가 없습니다 사본이 필요합니다. 원본 코드에 대해서는 아무것도 입력하지 마십시오. 을 금지합니다. 두 버전은 현재 설정에 따라 컴파일러에서 최적화를 트리거하는지 여부가 달라집니다.
    • 참고 : 상황에 따라이 최적화가 필수적인 경우가있는 C++ 17의 비트가 변경됩니다. 자세한 내용은 위의 링크를 참조하십시오.

편집 추가 할 :이 덧붙여, 명시 적으로 복사 생성자와 버전, 생성자가 일정하지 않은 참조를 복용 이례적인 일이다. 이것은 실제로 불변의 참조가 임시 Test(1)에 바인드 할 수 없으므로 어쨌든 사용할 수 없다는 것을 의미합니다. 나는이 oddness가 당신의 컴파일러가 copy elision을 수행하는 이유와 관련이 있다고 생각한다. 상수를 참조로 사용하도록 생성자를 변경하면 암시 적으로 복사 된 생성자와 마찬가지로 명시 적 복사 생성자가 호출되고 소멸자가 두 번 호출되면서 예상 한 동작을 볼 수 있습니다. (그러나 그것은 단지 내 부분에 대한 추측이므로 시도해보고보아야합니다!)

+0

흥미롭게도, g ++에서 똑같은 동작이 관찰 될 수 있습니다 (const 참조를 취하고'_tmain'의 이름을 바꾸기 위해 복사기를 고친 후). 복사기가 사소한 경우 컴파일러가 복사 실행을 수행하지 않는 것 같습니다 효과, 소멸자 호출을 피할 수 있지만 비트 복사로 끓는 복사 ctors 가진 멤버가 없습니다). 이것은 아마도 실제 코드에서 매우 드문 시나리오 일 것입니다. 3/5의 규칙으로 인해 사소한 복사본 생성자가있는 객체에도 사소한 소멸자가있는 것이므로 컴파일러가 불일치 할 때 컴파일러가 최적화를 방해하지 않는 이유입니다. – user4815162342

1

두 개의 Test 클래스 객체가 있습니다.인수를 값으로 전달하기 때문에 하나는 main 함수에 명시 적으로 생성되고, 다른 하나는 기본 복사 생성자로 생성되며 복사 생성자는 주석 처리됩니다. 두 개체 모두 파괴됩니다. 하나는 func()에서 나오고, 다른 하나는 main()에서 빠져 나옵니다. 따라서 두 명의 소멸자가 호출됩니다.

관련 문제