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声明:
有两种情况下,临时状态被摧毁 不同于完整表达的结束......
第二个上下文是引用绑定到临时的。该 临时引用的临时或临时的 引用绑定到的子对象的完整对象 在参考文件的生命周期内持续存在,除了:
...
VC11结果与copy elision有什么关系?它是VC11的错误吗?
回答者说:
分配给const引用的临时值直到const 参考超出范围
§12.2/ 5的例外列表不排除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!
即使const
被删除,VC11也会提供相同的功能。如果从g ++中删除const
,g ++仍会提供error: invalid initialization of non-const reference of type ‘scope_test&’ from an rvalue of type ‘scope_test’
。
答案 0 :(得分:2)
这两种行为都是正确的,当然根据C ++ 03标准(8.5.3 [dcl.init.ref]第5段):
否则,引用应为非易失性const类型(即,cv1应为const)。 [例如:......]
如果初始化表达式是rvalue,T2是类类型,并且“cv1 T1”与“cv2 T2”引用兼容,则引用以下列方式之一绑定(选择是实现-defined):
- 引用绑定到rvalue(参见3.10)表示的对象或该对象中的子对象。
- 创建临时类型为“cv1 T2”[sic],并调用构造函数将整个右值对象复制到临时对象中。引用绑定到临时或临时的子对象。
我认为C ++ 11的定义仍然允许复制,但措辞并不明确允许复制。无论如何,VC ++并不声称完全符合C ++ 11标准。