const 引用类成员是否会延长临时对象的寿命?

新手上路,请多包涵

为什么会这样:

 #include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

给出以下输出:

答案是:

代替:

答案是:四

原文由 Kyle 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

只有 本地 const 引用可以延长使用寿命。

该标准在第 8.5.35 节 [dcl.init.ref] 中指定了此类行为,这是关于引用声明的初始化程序的部分。您的示例中的引用绑定到构造函数的参数 n ,并且当对象 n 绑定超出范围时变得无效。

生命周期扩展不能通过函数参数传递。 §12.25 [class.temporary]:

第二个上下文是引用绑定到临时的。引用绑定到的临时对象或作为临时对象绑定的子对象的完整对象的临时对象将在引用的生命周期内持续存在,除非下面指定。临时绑定到构造函数的 ctor-initializer (§12.6.2 [class.base.init]) 中的引用成员将持续存在,直到构造函数退出。在函数调用(第 5.2.2 节 [expr.call])中临时绑定到引用参数会一直持续到包含调用的完整表达式完成为止。

原文由 Potatoswatter 发布,翻译遵循 CC BY-SA 3.0 许可协议

从其他答案中可以清楚地看出,类成员不会延长构造函数调用之后的临时生命周期。在某些情况下,您的 API 可以“安全地”假设传递给类的所有 const& 对象都不是临时对象,而是对范围良好的对象的引用。

如果您不想创建副本,您可以做些什么来确保 UB 不会潜入您的代码?您拥有的最佳工具是通过 将接受此类临时对象的重载声明为已删除, 来维护传递给构造函数的 std::string const& 不是临时对象的假设:

 #include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}

    Sandbox(string&&) = delete;
    // ^^^ This guy ;)

    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    // Detect you're trying ^^^ to bind a
    // reference to a temporary and refuse to compile

    return 0;
}

演示

原文由 Nikos Athanasiou 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题