2009-03-30 78 views
15

Tôi đã nghĩ rằng khi một hàm trả về một đối tượng trên ngăn xếp đến hàm gọi, hàm gọi sẽ nhận một bản sao của đối tượng ban đầu nhưng hàm hủy của đối tượng ban đầu được gọi ngay khi ngăn xếp thư giãn. Nhưng trong chương trình sau, destructor được gọi chỉ một lần. Tôi mong đợi nó sẽ được gọi hai lần.Tại sao hàm hủy không được gọi cho đối tượng được trả về từ hàm?

#include <iostream> 

class MyClass 
{ 
public: 
    ~MyClass() { std::cout << "destructor of MyClass" << std::endl; } 
}; 

MyClass getMyClass() 
{ 
    MyClass obj = MyClass(); 
    return obj; // dtor call for obj here? 
} 

int main() 
{ 
    MyClass myobj = getMyClass(); 
    return 0; // Another dtor call for myobj. 
} 

Nhưng "destructor MyClass" chỉ được in một lần. Giả định của tôi sai hay có cái gì khác đang xảy ra ở đây?

+0

Tại sao bạn viết: "MyClass obj = MyClass();" ? "MyClass obj;" sẽ làm tốt. Đây không phải là java;). –

+0

Có, đó là do lập trình rất nhiều trong Java trước đây :) – Srikanth

+0

@EvanTeran "_Tại sao bạn viết:" MyClass obj = MyClass(); "?" MyClass obj; "sẽ làm tốt" "đây là ** không ** tương đương nói chung. – curiousguy

Trả lời

21

Đây là trường hợp đặc biệt khi trình biên dịch được phép tối ưu hóa bản sao: đây được gọi là named return value optimization (NRVO). Về cơ bản, trình biên dịch cấp phát bộ nhớ cho đối tượng trả về trên trang gọi và cho phép hàm điền trực tiếp vào bộ nhớ đó thay vì tạo đối tượng tại trang được gọi và sao chép nó trở lại. Trình biên dịch hiện đại làm điều này thường xuyên bất cứ khi nào có thể (có một số tình huống mà điều này không dễ dàng vì có một số đường dẫn trả về trong hàm trả về các phiên bản khác nhau).

Các vấn đề liên quan