C++
我正在尝试了解 const 引用如何延长临时对象的生命周期。我正在运行 one of the answers to What are the differences between pointer variable and reference variable in C++? 中的代码片段并在 VC11 和 g++ 4.8 之间得到了冲突的结果。我在这里扩展了代码段:
#include <stdio.h>
struct scope_test
{
~scope_test() { printf("scope_test done!\n"); }
};
int main()
{
const scope_test& test = scope_test();
printf("in scope\n");
}
回答者得到结果:
in scope
scope_test done!
我在 VC11 中试过了,得到了这个:
scope_test done!
in scope
scope_test done!
我假设 VC11 结果是由缺少复制省略引起的,所以我尝试查看是否使用 fno-elide-constructors
在 g++ 上禁用复制省略。会给出与 VC11 相同的结果。 (我不认为复制省略可以在 VC11 中切换。)但是,无论标志的设置如何,g++ 都会给出回答者的结果。
C++11 标准、ISO/IEC 14882:2011(E)、§12.2/4 和/5 指出:
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression...
The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
...
VC11 结果与复制省略有什么关系吗?是 VC11 错误吗?
回答者说:
temporaries assigned to const references live until the const reference goes out of scope
§12.2/5 的异常(exception)列表不排除 non-const
引用。标准中缺少什么?
在 VC11 中删除 const 会产生与带有 const 的 VC11 相同的结果。删除 g++ 中的 const 给出 error: invalid initialization of non-const reference of type ‘scope_test&’ from an rvalue of type ‘scope_test’
.为什么会有差异?
编辑:
我添加了复制和移动构造函数并尝试:
#include <stdio.h>
struct scope_test
{
scope_test() { printf("regular ctor\n"); }
scope_test(const scope_test& src) { printf("copy ctor\n"); }
scope_test(scope_test&& src) { printf("move ctor\n"); }
~scope_test() { printf("scope_test done!\n"); }
};
int main()
{
const scope_test& test= scope_test();
printf("in scope\n");
}
无论是否切换复制省略,g++ 都会给出:
regular ctor
in scope
scope_test done!
VC11 给出了同样的东西,即使 const
已移除。如果const
从 g++ 中删除,g++ 仍然给出 error: invalid initialization of non-const reference of type ‘scope_test&’ from an rvalue of type ‘scope_test’
.
最佳答案
这两种行为都是正确的,当然符合 C++03 标准(8.5.3 [dcl.init.ref] 第 5 段):
Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const). [Example: ...]
If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):
— The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.
我认为 C++11 的定义仍然允许进行复制,但措辞并没有明确允许复制。无论如何,VC++ 并不声称完全符合 C++11。
关于c++ - 通过 const 引用延长临时生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19306984/