2010-12-09 2 views
7
TestObject getObject(){ 
    TestObject a(5.0f); 
    return a; 
} 

int main(){ 
    TestObject a = getObject(); 
} 

C++에서 반환 된 객체는 반환 될 때 소멸자가 호출되지 않습니다. 객체가 함수 호출에서 차지한 메모리가 소멸자를 실행하지 않고 단순히 삭제 되었습니까? 나는이 소멸자를 실행하면C++ 객체 반환

확인을 구체적인 예 ..

#include <iostream> 

class Test{ 
public: 
Test(){}; 
~Test(){std::cout << "Goodbye cruel world\n";} 
}; 


Test getAnObject(){ 
Test a; 
return a; 
} 

int main(){ 
Test a = getAnObject(); 
} 

가 한 번만 실행 (안 getAnObject의 로컬 개체에 대한()). 이것이 항상 사실이라고 생각할 수 있습니까? 망막 정맥 폐쇄의이 테스트는 getanobject에서 두 개체의 소멸자 실행이 가이드() 및 주요 기능에 따라

#include <iostream> 

class Test{ 
public: 
Test(){}; 
~Test(){std::cout << "Goodbye cruel world\n";} 
}; 


Test getAnObject(){ 
Test a; 
Test b; 
int i = 0; 
if (i){ 
    return a; 
}else{ 
    return b; 
} 
} 

int main(){ 
Test a = getAnObject(); 
} 

. 일관된 행동을 보장하기 위해 항상 3 가지 규칙을 구현해야하는 경우입니까?

+5

getObject는 TestObject가 아닌 int를 반환하도록 프로토 타입 화됩니다. – Max

+0

죄송합니다. 감사. – Guest300000000

답변

9

소멸자를 실행하면 소멸자가 getAnObject()의 로컬 객체가 아니라 한 번만 실행됩니다.이것이 항상 사실이라고 생각할 수 있습니까?

정확성을 위해? 효율성을 위해서? 예. -ish.

자세히 설명하면 : 엄밀히 말하면 함수에서 반환 할 때 로컬 객체가 복사됩니다. 그런 다음 로컬 저장소는 로컬 개체의 소멸자를 호출하여 정리됩니다.

그러나 컴파일러는 동일한 관찰 가능한 동작을 산출하는 다른 코드를 자유롭게 생성 할 수 있습니다. 특히, 표준은 컴파일러에게 반환 값의 복사를 삭제할 권한을 부여하고 두 객체 (로컬 객체와 반환 값의 수신 객체)에 대해 동일한 저장 위치를 ​​다시 사용합니다. 이렇게하면 컴파일러는 복사 생성자 나 소멸자 (동일한 메모리 위치를 다시 사용하기 때문에)를 호출 할 필요가 없을 수 있습니다.

그러나이 최적화 ("명명 된 반환 값 최적화"라고도 함, NRVO)는 표준에 의해 보장되지 않으며 실제로 모든 곳에서 수행 할 수 없습니다. 너 수 없다면 그것이 정확을 위해 일어날 것이라고 가정합니다. 특히 객체 은 여전히 ​​에 잘 정의 된 복사 생성자와 소멸자가 필요합니다. 그렇지 않으면 프로그램이 이 아닌입니다.

한편, 모든 최신 컴파일러가이 최적화가 가능할 때 어디서나이 최적화를 수행 할 수 있습니다. 따라서 성능 측면에서이 최적화에 의존 할 수 있습니다 (일반적으로).

+1

잘못되었습니다. 프로그램이 잘못 구성되어 있고 진단이 필요하므로 실제로 행동이 잘 정의되어 있습니다. – Yttrill

+0

@ Yttrill : 고마워요. 진단이 필요한지 확실하지 않았습니다. –

3

getObject()a 사본을 반환합니다. 컴파일러가 최적화를 수행하지 않으면 어떻게 될까요? a의 임시 사본은 복사 생성자 TestObject을 사용하여 생성됩니다. 그런 다음 원래 a이 소멸되고 소멸자가 호출 된 다음 임시 객체가 함수의 로컬 변수 a에 복사됩니다. 임시도 파괴되고 소멸자가 호출됩니다.

getObject()의 반환 값은이 특별한 경우 변수에 즉시 할당되므로 현대 컴파일러는 최소한 하나 이상의 복사 작업을 최적화 할 수 있습니다.

+0

'int getObject()'는 int를 반환해야합니다. 나는 반드시 –

+0

일 필요는 없습니다. 그것은 다른 사람들이 RVO로 말했듯이 최적화 될 수 있습니다. – tenfour

+1

@tenfour, 내가 최적화에 대해 말하지 않고,이 함수가'TestObject'가 아닌'int'를 리턴하고 있다는 사실을 지적하고있었습니다. –

0

으로 getObject()는의 사본을 반환하고,으로 getObject에서 만든 원래 목적은 기능을 종료에 파괴하지만, 반환 값 최적화가있을 수있다 (에 따라 달라집니다 사용중인 컴파일러).

0

예제의 일치하지 않는 반환 유형 외에도 return value optimization 또는 일반적으로 copy elision을 찾고있을 수 있습니다. 만약 내가 정확하게 기억하고 있다면, 복사 엘레멘트 규칙은 다소 모호하지만 C++ 표준으로 명시되어있다.

-1

getObject에서 스택에 TestObject를 작성 중이므로 반환 값이 유효하지 않습니다. 힙에 오브젝트를 작성하려면 "new"를 사용하십시오. 메서드의 범위가 종료 될 때 소멸자가 호출된다고 나는 믿지 않습니다. 스택의 메모리를 단순히 회수한다고 생각합니다.

+2

아니요 - 이것이 잘못되었습니다. –

+0

@Konrad가 호출되는 복사 생성자입니까? 정교하게 제발 ... – flatline

+0

@flatline : depends. 어쨌든,이 코드는 절대적으로 유효합니다. 복사 생성자가 호출되는지 여부는 컴파일러가 코드를 최적화할지 여부에 따라 다릅니다. –

0

함수 호출시 개체가 차지한 메모리는 소멸자를 실행하지 않고 단순히 삭제 되었습니까?

아니요. 최적화를 사용하지 않으면 로컬 개체가 소멸되고 소멸자가 호출됩니다. 복사 - 추출 최적화가 수행되면, 로컬 객체는 main에있는 하나의 객체에 대한 "참조"(따옴표에 주목)가됩니다.이 경우 소멸자는 함수 내에서 실행되지 않지만 메모리는 그렇지 않습니다. 어느 쪽도 할당 해제.