为啥我们可以非常量引用临时对象并延长其生命周期?

Posted

技术标签:

【中文标题】为啥我们可以非常量引用临时对象并延长其生命周期?【英文标题】:Why can we non-const reference to a temporary object and prolong its lifetime?为什么我们可以非常量引用临时对象并延长其生命周期? 【发布时间】:2013-11-02 07:51:14 【问题描述】:
#include <iostream>

using namespace std;

struct A

    A()
        : _p(new int(1))
    

    ~A()
    
        *_p = 0;

        delete _p;
        _p = nullptr;
    

    int* _p;
;

int main()

    //
    // Let r_to_a reference to a temporary object
    //
    A& r_to_a = A();

    //
    // Is r_to_a still valid now?
    //
    cout << *r_to_a._p << endl; // Output : 1 instead of a run-time error

据我所知,非常量引用临时对象的格式不正确。但是,上面的代码表明它在 C++ 中似乎是合法的。为什么?

我的编译器是 VC++ 2013。

【问题讨论】:

【参考方案1】:

代码并没有真正表明它在 C++ 中是合法的。它只是表明您的编译器支持非标准编译器扩展。您必须查阅编译器文档以了解临时文件的生命周期是否延长。您的实验似乎表明它已扩展。

不过,您的代码在标准 C++ 中格式不正确。如果您使用 /Za 选项禁用该编译器中的编译器扩展,它也会拒绝接受您的代码:

error C2440: 'initializing' : cannot convert from 'A' to 'A &'

或者,为了避免使用/Za(显然已损坏),您可以这样做

#pragma warning(error : 4239)

或者更改C/C++ -&gt; Advanced -&gt; Treat Specific Warnings As Errors下对应的项目设置,更有针对性地禁止该特定功能。

【讨论】:

当您明确禁用扩展时,它也将无法编译自己的标头;-) @rubenvb:我的印象是它可能无法在禁用扩展的情况下编译 WindowsAPI 标头。但是标准头文件应该是可编译的。 (如果我错了,请纠正我。) @AndreyT:我确定我记得关于这方面的一些大行:在某些时候,MSVC 的库实现者正式宣布他们不支持/Za。可能是因为/Za 模式中存在错误?我的印象是这包括标准库,但我不记得细节(甚至不记得它是什么标题),并且可能从那时起它已经被修复了。 它只是坏了。请参阅here 了解 STL(首字母,而不是首字母缩写词)给 Clang 开发人员的官方消息,他们显然使用了强制标准执行的选项。 @rubenvb:是的,我认为就是这样。请注意,/W4“警告大多数扩展”,我认为这是一种说法,“编译器团队没有计划发布符合要求的实现,所以我们,图书馆团队,洗手”;-)

以上是关于为啥我们可以非常量引用临时对象并延长其生命周期?的主要内容,如果未能解决你的问题,请参考以下文章

为啥非常量引用不能绑定到临时对象?

这个对象生命周期扩展闭包是 C# 编译器错误吗?

左值与右值的根本区别在于能否获取内存地址,而能否赋值不是区分的依据

在构造函数之外延长 QT 对象的生命周期

c++中为啥要函数返回引用?

如何在 Symfony 中延长会话 cookie 的生命周期?