2011-04-20 34 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

相关问题