Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这是否会遇到有关对象生命周期的未定义行为?_C++_Undefined Behavior - Fatal编程技术网

C++ 这是否会遇到有关对象生命周期的未定义行为?

C++ 这是否会遇到有关对象生命周期的未定义行为?,c++,undefined-behavior,C++,Undefined Behavior,可见输出: #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 为什么??临时的生命直到完整表达结束。你看到的行为是标准规定的行

可见输出:

#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
C()(即分号)。这就是为什么我认为输出是明确定义的

本标准第§12.2/3节内容如下:

[…]临时对象作为评估的最后一步被销毁 完整表达式(1.9)(在词汇上)包含它们的创建点。即使评估以抛出异常结束,这也是正确的

需要强调的是,在本例中,临时变量的生存期与函数
I()
的reference或const reference参数无关。即使
I()
的签名是:

V(I(C()));
临时表达式将一直持续到完整表达式的完成,您将看到完全相同的输出


请参见:

V
的调用在完全计算完整表达式之前返回。当
V
返回时,它将打印其内容(从
V
返回之前有一个序列点)


临时的
C()
只有在计算完完整表达式后才会被销毁。

为什么会这样?如果我()返回常量C&,该怎么办?临时表达式的生存期必须至少与它所嵌入的表达式的持续时间相同。@mcmcc:is
I(C())
所嵌入的表达式是
I(C())
。整行是表达式语句。请参阅更新的答案。现在它完全正确了。因此,实际上,临时表达式的生存期是所有封闭表达式的范围,而不仅仅是直接封闭表达式(在本例中为
I(C())
)?@BCS:Yes。请参阅我的帖子和标准中的引用。:-)@Nawaz你的答案是,生命周期与完整表达式结束时一样长,因为它绑定到一个引用。但这与推荐人无关。临时表达式将一直存在到完整表达式的结尾,与任何引用无关。@Johannes:但是标准说它与引用有关:-/@Nawaz该规范一般说来是关于临时对象的,“临时对象被销毁,作为评估完整表达式(1.9)的最后一步,该表达式(词汇上)包含临时对象创建的点。”。它只是有关于引用的声明,因为在它之前,它说“引用绑定到的临时性[…]在引用的生命周期内持续存在,除非下面指定。”,而您引用的文本就是这样一个例外。因此,即使您将临时文件的地址作为指针传递(例如,
C().getThisPtr()
),它仍然是安全的。如果临时文件可以在仅计算直接包含的表达式后合法销毁,那么该堆栈空间可以用于计算表达式的其余部分。考虑到历史上对表达式求值的宽松规则,这似乎是合理的。
int I(C c); //instead of : int I(const C & c);