2011-03-19 3 views
2

below code에서 A이라는 익명의 변수를 B의 ctor에 전달하면 해당 변수가 해당 줄 뒤에 소멸됩니다. this answer에 따르면개체, 범위, RAII의 수명 이해

임시 객체가 전체 식의 끝에 파괴 그들은의 부분입니다. 전체 표현식은 다른 표현식의 하위 표현식 이 아닌 표현식입니다. 대개이 은 ; (or) for if, while, switch etc.)으로 끝나며이 문장의 끝 부분이 임을 나타냅니다.

나는 그것을 얻을하지만이 파괴 된 후 어떻게 클래스 B는 그 mamber_a 변수의 값을 알 수 있습니까? 나는 A의 복사본 ctor가 불리는 것을 안다. 이것이 어떻게 가능한지?

#include <iostream> 
using namespace std; 

class A 
{ 
     int sign; 
     A(); 
     const A & operator=(const A &); 
public: 
     A(int x) : sign(x) { 
       cout << "A ctor : " << sign << endl; 
     } 

     void WriteA() const { 
       cout << sign << endl; 
     } 

     ~A() { 
       cout << "A dtor : " << sign << endl; 
     } 

     A(const A &) { 
       cout << "A copied : " << sign << endl; 
     } 
}; 

class B 
{ 
     int sign; 
     const A & member_a; 
public: 
     B(const A & aa , int ww) : sign (ww) ,member_a(aa) { 
       cout << "B ctor : " << sign << endl; 
     } 

     void WriteB() const { 
       cout << "Value of member_a :"; 
       member_a.WriteA();  
     } 

     ~B() { 
       cout << "B dtor : " << sign << endl; 
     } 
}; 

int main() { 
     A a(10); 
     B b1(a,1); 
     b1.WriteB();  

     B b2(A(20),2); 
     b2.WriteB(); 

     return 0; 
} 

출력은 다음과 같습니다

A ctor : 10 
B ctor : 1 
Value of member_a :10 
A ctor : 20 
B ctor : 2 
A dtor : 20 
Value of member_a :20 // Object A was destructed. Where does this 20 come from? 
B dtor : 2 
B dtor : 1 
A dtor : 10 

답변

5

당신은 member_a이 값 (20)을 가지고 순수 기회 C++

의 까다로운 부분 중 하나가 당신은에 주심을 무엇 타격 정의되지 않은 동작.

클래스가 외부 객체에 대한 참조를 유지할 때 객체의 수명이 참조되는 객체보다 오래 지속되는지 확인하는 것은 프로그래머의 책임입니다. 이 경우 member_a.WriteA();으로 전화하면 개체가 이미 파괴되어 잠재적으로 사용자가 속하지 않은 메모리에 액세스하고있는 것입니다 (이 경우 우연히 덮어 쓰지 않은 근처의 위치에있는 것입니다)).

개체에 대한 참조를 유지하려는 경우. 당신은 const 참조를 유지할 수 있지만 실수로 임시 값을 전달할 수 없도록 매개 변수를 일반 참조로 만드는 것이 가장 좋은 경우가 있습니다 (참조로 const 객체를 전달해야하므로 항상 작동하지는 않습니다).

1

파괴 된 개체에 대한 참조를 사용하는 것은 "정의되지 않은 동작"입니다.

A의 소멸자에서 "부호"를 "-1"로 설정하고 어떻게되는지보십시오. 확률은 "WriteB"에 대한 호출이 당신이 사망 한 물건에 메시지를 보낸 것을 보여줍니다.

이제 b2의 생성자와 b2.WriteB에 대한 호출 (예 : 서브 루틴 호출) 사이에 코드를 사용하여 스택을 넣으십시오. 이제 통화가 다른 것을 인쇄하는 것을 알게 될 것입니다.