2012-09-23 13 views
10

tôi nghĩ tài liệu tham khảo chỉ kéo dài tuổi thọ của temporaries đến tuổi thọ của các tài liệu tham khảo chính nó, nhưng đầu ra của đoạn sau đây dường như mâu thuẫn:Thời gian tồn tại của đối số mặc định tạm thời bị ràng buộc với tham số tham chiếu là gì?

#include <iostream> 

struct X{ ~X(){ std::cout << "Goodbye, cruel world!\n"; } }; 

X const& f(X const& x = X()){ 
    std::cout << "Inside f()\n"; 
    return x; 
} 

void g(X const& x){ 
    std::cout << "Inside g()\n"; 
} 

int main(){ 
    g(f()); 
} 

Live example. Output:

Inside f() 
Inside g() 
Goodbye, cruel world! 

Vì vậy, có vẻ như các tạm thời bị phá hủy sau khi g() được gọi là ... những gì cho?

+0

Nó thường được coi là không thân thiện để không để lại một lời giải thích khi downvoting. – Xeo

+0

Đoán của tôi là downvoter vô tình nhấn nút downvote khi họ thực sự có nghĩa là để nhấn nút upvote (nhìn vào tổng số phiếu cho câu trả lời của bạn và câu hỏi cũng hỗ trợ lý thuyết này). Nhưng ai biết được! –

+0

@Jesse: Lý thuyết hay, nhưng câu trả lời có nhiều ý nghĩa hơn so với câu hỏi trước khi downvote xuất hiện. :) – Xeo

Trả lời

13

Tiêu chuẩn xử lý này trong trường hợp đặc biệt trong §12.2 [class.temporary]:

p4 Có hai tình huống trong đó là tạm thời bị phá hủy tại một điểm khác biệt so với khi kết thúc đầy đủ thể hiện. [...]

p5 Ngữ cảnh thứ hai là khi tham chiếu bị ràng buộc tạm thời. Tạm thời mà tham chiếu bị ràng buộc hoặc tạm thời là đối tượng hoàn chỉnh của một đối tượng con mà tham chiếu bị ràng buộc vẫn tồn tại trong suốt thời gian tham chiếu ngoại trừ:

  • Giới hạn tạm thời tham số tham chiếu trong hàm cuộc gọi (5.2.2) vẫn tiếp tục cho đến khi hoàn thành biểu thức đầy đủ có chứa số gọi.

Các tiêu chuẩn cũng có một lưu ý tiện dụng trên toàn biểu hiện và đánh giá các subexpressions của họ liên quan đến các thông số mặc định trong §1.9 [intro.execution] p11:

[Lưu ý: Việc thẩm định full- biểu thức có thể bao gồm việc đánh giá các biểu thức con không phải là một phần từ vựng của biểu thức đầy đủ. Ví dụ, các biểu thức con liên quan đến việc đánh giá đối số mặc định (8.3.6) được coi là được tạo trong biểu thức gọi hàm, không phải biểu thức xác định đối số mặc định. —thêm ghi chú]

1

Thú vị, +1. (Tôi không có nghĩa là để cạnh tranh với câu trả lời tự tốt đẹp của bạn ở đây). Chỉ cần một lưu ý phụ cho bất cứ ai quan tâm. Nếu bạn muốn có một hiệu ứng tương tự nhưng cho phép không const bạn có thể sử dụng ngữ nghĩa di chuyển:

#include <iostream> 

struct X{ 
    ~X(){ std::cout << "Goodbye, cruel world!\n"; } 
    X(X && x){ std::cout << "moved "; } 
    X(){} 
}; 

X f(X x = X()){ 
    std::cout << "Inside f()\n"; 
    return x; 
} 

void g(X x){ 
    std::cout << "Inside g()\n"; 
} 

int main(){ 
    g(f()); 
} 

cho

Inside f() 
moved Inside g() 
Goodbye, cruel world! 
Goodbye, cruel world! 
+0

Bạn cũng có thể sử dụng 'X &&' và trả về 'std :: move (x)'. :) – Xeo

+0

@Giovanni tuyên bố của bạn là không rõ ràng nếu không sai. –

+1

@Xeo "return std :: move (x)" nên tránh trong trường hợp này, xem thêm chi tiết, ví dụ tại https://stackoverflow.com/questions/14856344/when-should-stdmove-be-used-on-a -function-return-value –