2012-09-24 6 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; 
} 

chương trình sẽ đầu ra:Tại sao destructor của tôi xuất hiện để được gọi thường xuyên hơn so với các nhà xây dựng?

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

Các constructor và destructor không xuất hiện theo cặp?

+0

Chào mừng bạn đến với Stack Overflow! 1 và cảm ơn bạn đã cung cấp một chương trình mẫu hoàn chỉnh. Xem http://SSCCE.ORG vì lý do quan trọng. –

+1

Sao chép contructor được gọi bởi 'return x;' rõ ràng đã được tối ưu hóa, nhưng tôi tự hỏi liệu một trình tối ưu hóa đủ mạnh có thể loại bỏ lời gọi khi gọi 'f' (' x' được truyền theo giá trị) hay không. Vì vậy, có hiệu quả bạn gọi destructor mặc định một lần và sau đó các nhà xây dựng bản sao một lần. –

+1

@FrerichRaabe: tối ưu hóa đó sẽ không phù hợp với tiêu chuẩn, cho phép người tạo bản sao bỏ qua chỉ trong một số trường hợp nhất định. Trong tất cả các trường hợp được phép, nguồn hoặc đích của bản sao ưu tiên là tạm thời. –

Trả lời

14

Bạn cần phải thêm một hàm tạo bản sao làm tăng bộ đếm.

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

Nếu bạn không thêm nó một cách rõ ràng, trình biên dịch sẽ tạo một mã không có gì với bộ đếm cnt.

biểu hiện này

A a1 = f(a0); 

đang tạo ra các bản sao của a0, mà tận dụng các constructor sao chép. Số bản sao chính xác có thể thay đổi tùy theo copy elision, nhưng cnt của bạn phải là 0 ở cuối chương trình.

Note: Trong C++ 11, bạn cũng nên xem xét khả năng của một trình biên dịch tạo ra di chuyển bản sao constructor, tuy nhiên, một khi bạn khai báo constructor sao chép của riêng bạn, trình biên dịch không còn tạo ra các phiên bản di chuyển.

3

Bạn cũng cần đếm số lần gọi hàm sao chép. Trong C++ 11 cũng có các hàm khởi tạo cần phải được tính đến.

5

Bạn không theo dõi tất cả các nhà xây dựng, chỉ là hàm tạo mặc định. Trình biên dịch đã tạo ra một hàm tạo bản sao và sử dụng nó một vài lần, kế toán cho 2 đối tượng được liệt kê là bị hủy và không được tạo ra.