2011-04-20 23 views
2
#include "stdio.h" 

class C { 
public: 
    ~C() { printf("~C\n"); } 
}; 

int I(const C& c) { printf("I\n"); return 0; } 
void V(int i) { printf("V\n"); } 

int main() { 
    V(I(C())); 
    return 0; 
} 

看輸出:這是否會遇到有關物體壽命的未定義行爲?

I 
V 
~C 

我本來期望:

I 
~C 
V 
+0

你爲什麼期待?如果我()返回const C&?臨時的生命週期至少要持續嵌入表達式的持續時間。 – mcmcc 2011-04-20 16:01:19

+0

@mcmcc:C()嵌入的表達式是I(C())'。整行是一個表達式*語句*。 – BCS 2011-04-20 16:05:50

+0

查看已更新的答案。現在它完全正確。 – Nawaz 2011-04-20 16:31:52

回答

4
V(I(C())); 

C()創建一個臨時其仍然存在直到充分表達的完成,和充分表達的完成是;(即分號)。這就是爲什麼你看到我認爲的輸出是明確的。

第§12.2/ 3從標準讀取,

[...]臨時對象評估 全表達(1.9)破壞作爲最後的步驟,(詞彙)包含它們的創建點。即使評估以拋出異常結束,情況也是如此。

只是強調,在這個例子中,臨時的壽命有無關的功能I()參考const引用參數。即使I()的簽名是:

int I(C c); //instead of : int I(const C & c); 

臨時會堅持,直到表達的完成,你會看到完全相同相同的輸出。

看到這個:http://www.ideone.com/RYWhy

1

爲什麼?臨時的生活直到完整的表達式結束。

+0

如果在僅評估直接包含的表達式後臨時數據可能會被合法銷燬,那麼該堆棧空間可用於評估表達式的其餘部分。鑑於歷史上關於表達評估的寬鬆規則,這似乎是合理的。 – BCS 2011-04-20 16:11:15

1

您所看到的行爲是由標準強制要求的行爲:在完整表達式創建結束時銷燬臨時對象。

從歷史上看,可以看到另一種行爲(並且在某些編譯器中仍然可用):在塊的末尾銷燬。在你的情況下,它不會造成任何影響,因爲它會進一步推遲破壞。

3

充分表達之前V的調用返回已完全評估。當V已經返回時,它會打印它的東西(從V返回之前有一個順序點)。

臨時C()僅在評估完整的完整表達式後才銷燬。

+0

因此,實際上,臨時的生命週期是所有封閉表達式的範圍,而不僅僅是直接封閉的表達式(在這種情況下是'I(C())')? – BCS 2011-04-20 16:08:01

+0

@BCS:是的。查看我的帖子和標準報價。 :-) – Nawaz 2011-04-20 16:08:54

+0

@Nawaz你的答案說,一生只要到完整表達式結束,因爲它被綁定到一個引用。但它並不是真的需要參考。臨時表達式將一直存在,直到完全表達式的結尾獨立於任何引用。 – 2011-04-20 16:12:54

相關問題