2013-04-21 33 views
5

Tôi đã mã đơn giản sau đây:Constructor/Destructor trật tự cuộc gọi trên đống

class A 
{ 
    int a; 
public: 
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; } 
    ~A()   { cout << "Destructor a=" << a << endl; } 
    void print() { cout << "Print  a=" << a << endl; } 
}; 

void f() 
{ 
    A a(1); 
    a.print(); 
    a = A(2); 
    a.print(); 
} 

int main() 
{ 
    f(); 
    return 0; 
} 

Đầu ra là:

Constructor a=1 
Print  a=1 
Constructor a=2 
Destructor a=2 
Print  a=2 
Destructor a=2 

tôi thấy rằng có hai cuộc gọi destructor với a=2 và không có a=1 khi có một lời gọi hàm tạo cho mỗi trường hợp. Vậy các contructors và destructros được gọi như thế nào trong trường hợp này?

+1

Tại sao bạn mong đợi cuộc gọi hủy với 'a = 1'? – juanchopanza

+2

Bạn có nhận ra giá trị 'A' tạm thời không? Nó không sống rất lâu. –

+0

Tôi đã phát hiện ra nó bây giờ là Kerrek. Wow câu trả lời đang đổ vào. Tôi thấy rõ ràng. Cảm ơn mọi người. – SolidSun

Trả lời

2

Điều này là do bạn không phá hủy A(1) bạn đang gán A(2) với nó, chúng ta hãy mở rộng ví dụ của bạn bằng cách thêm assign operator:

class A 
{ 
    int a; 
public: 
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; } 
    ~A()   { cout << "Destructor a=" << a << endl; } 
    void print() { cout << "Print  a=" << a << endl; } 
    A &operator=(const A &other) { 
     cout << "Assign operator old=" << a << " a=" << other.a << endl; 
     a = other.a; 
    } 
}; 

Mà sẽ dẫn đến:

[[email protected] tmp]$ ./a.out 
Constructor a=1 
Print  a=1 
Constructor a=2 
Assign operator old=1 a=2 <- This line explains why destructor is not called 
Destructor a=2 
Print  a=2 
Destructor a=2 

Nếu bạn có một trong những thực hiện:

  • Destructor - Destruct tất cả các thành viên của đối tượng
  • Sao chép constructor - Xây dựng tất cả các thành viên của đối tượng từ các thành viên tương đương trong tham số của hàm tạo bản sao
  • Sao chép toán tử gán - Chỉ định tất cả thành viên của đối tượng từ các thành viên tương đương trong tham số của toán tử gán

bạn nên thực hiện tất cả chúng. Điều này được gọi là rule of three.

7
a = A(2); 

sẽ sử dụng mặc định operator= để gán giá trị mới cho a, thiết lập giá trị của nó a::a thành viên 2.

void f() 
{ 
    A a(1);//a created with int constructor a.a == 1 
    a.print();// print with a.a == 1 
    a = A(2);//Another A created with int constructor setting a.a == 2 and immediately assigning that object to a 
    //object created with A(2) deleted printing 2 it was created with 
    a.print();//a.a==2 after assign 
}//a deleted printing 2 it was assigned with 

Bạn có lẽ nên đọc về Rule of three để có được sự hiểu biết tốt hơn những gì đang xảy ra.

4
void f() 
{ 
    A a(1); 
     // Constructor a=1 
    a.print(); 
     // Print  a=1 
    a = A(2); 
     // Constructor a=2 
     // also operator= 
     // Destructor a=2 
    a.print(); 
     // Print  a=2 
     // Destructor a=2 
} 
1

Đầu tiên các nhà xây dựng cho a = 1 được gọi là

Second in được gọi là

Thứ ba đối tượng mới mà bạn đã tạo A (2) đã xây dựng nó được gọi là.

Fourth đối tượng này được gán cho đối tượng thành viên dữ liệu để các đối tượng a = 2

Fifth destructor cho đối tượng A (2) được gọi là

Thứ sáu destructor cho đối tượng một được gọi là

2
void f() 
{ 
    A a(1); // Constructor a=1 (a.a(1) is called) 
    a.print(); // Print a=1 
    a = A(2); // Constructor a=2 (Temporary unnamed object A(2) is constructed) 
       // compiler generated a.operator=(const A&); is called and then 
       // Destructor a=2 (Temporary unnamed object is destroyed. 
    a.print(); // Print a=2 
       // Destructor a=2 (a.~a() is called) 
} 
Các vấn đề liên quan