c++ - 通过 const 引用延长临时生命周期

标签 c++ object-lifetime temporary-objects const-reference scopeguard

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/

相关文章:

c++ - 在分块矩阵中查找一个值

c++ - 获取未初始化对象成员的地址是否定义明确?

c++ - 临时绑定(bind)到引用参数的默认参数的生命周期是多少?

子进程中的 C++ windows LocalSystem 模拟失败

c++ - LLVM:即时编译的简单示例

c++ - 抽象类/接口(interface) C++

objective-c - 在委托(delegate)回调期间应该如何延长委托(delegate)对象的生命周期?

c++:何时销毁临时对象

c++ - 为什么在范围末尾销毁临时对象后 C++ 程序崩溃