C++ const引用类成员是否延长了临时类的寿命?

C++ const引用类成员是否延长了临时类的寿命?,c++,temporary,ctor-initializer,const-reference,C++,Temporary,Ctor Initializer,Const Reference,为什么会这样: #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 <&

为什么会这样:

#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;
}
#包括
#包括
使用名称空间std;
类沙箱
{
公众:
沙盒(conststring&n):成员(n){}
常量字符串和成员;
};
int main()
{
沙箱沙箱(串(“四”));
不能只有局部
const
引用可以延长寿命

本标准在§8.5.3/5、[dcl.init.ref]中规定了此类行为,这是关于引用声明的初始值设定项的一节。示例中的引用绑定到构造函数的参数
n
,当对象
n
绑定到超出范围时,该引用将无效

生存期扩展不能通过函数参数传递。§12.2/5[类.临时]:

第二个上下文是引用绑定到临时对象时的上下文。该引用绑定到的临时对象或该临时对象绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,以下指定的情况除外。临时绑定到构造函数中的引用成员zer(§12.6.2[class.base.init])持续存在,直到构造函数退出。函数调用(§5.2.2[expr.call])中引用参数的临时绑定持续存在,直到包含调用的完整表达式完成

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

本标准在§8.5.3/5、[dcl.init.ref]中规定了此类行为,这是关于引用声明的初始值设定项的一节。示例中的引用绑定到构造函数的参数
n
,当对象
n
绑定到超出范围时,该引用将无效

生存期扩展不能通过函数参数传递。§12.2/5[类.临时]:

第二个上下文是引用绑定到临时对象时的上下文。该引用绑定到的临时对象或该临时对象绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,以下指定的情况除外。临时绑定到构造函数中的引用成员zer(§12.6.2[class.base.init])持续存在,直到构造函数退出。函数调用(§5.2.2[expr.call])中引用参数的临时绑定持续存在,直到包含调用的完整表达式完成


因为一旦沙盒构造函数返回,您的临时字符串就超出了范围,并且它占用的堆栈被回收用于其他目的


通常,您不应该长期保留引用。引用适用于参数或局部变量,而不适用于类成员。

因为一旦沙盒构造函数返回,您的临时字符串就超出了范围,并且它占用的堆栈已被回收用于其他目的


通常,您不应长期保留引用。引用适用于参数或局部变量,而不适用于类成员。

以下是解释所发生情况的最简单方法:

大体上您创建了一个字符串并将其传递到构造函数中。此字符串实例仅存在于构造函数中。在构造函数中,您指定成员直接指向此实例。当作用域离开构造函数时,字符串实例被销毁,然后成员指向不再存在的字符串对象。使用Sandbox、 指向其作用域之外引用的成员点将不会在作用域中保留这些外部实例

如果要修复程序以显示所需的行为,请进行以下更改:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}
intmain()
{
字符串温度=字符串(“四”);
沙箱(温度);

cout下面是解释发生了什么的最简单方法:

大体上您创建了一个字符串并将其传递到构造函数中。此字符串实例仅存在于构造函数中。在构造函数中,您指定成员直接指向此实例。当作用域离开构造函数时,字符串实例被销毁,然后成员指向不再存在的字符串对象。使用Sandbox、 指向其作用域之外引用的成员点将不会在作用域中保留这些外部实例

如果要修复程序以显示所需的行为,请进行以下更改:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}
intmain()
{
字符串温度=字符串(“四”);
沙箱(温度);

cout从技术上讲,这个程序实际上不需要将任何内容输出到标准输出(首先是一个缓冲流)


  • 从技术上讲,
    cout这个程序实际上不需要将任何东西输出到标准输出(这是一个缓冲流)


    • cout你指的是某个已经消失的东西

      #include <string>
      #include <iostream>
      
      class Sandbox
      {
      
      public:
          const string member = " "; //default to whatever is the requirement
          Sandbox(const string& n) : member(n) {}//a copy is made
      
      };
      
      int main()
      {
          Sandbox sandbox(string("four"));
          std::cout << "The answer is: " << sandbox.member << std::endl;
          return 0;
      }
      
      #包括
      #包括
      类沙箱
      {
      公众:
      const string member=“;//默认为任何要求
      沙盒(conststring&n):成员(n){}//创建了一个副本
      };
      int main()
      {
      沙箱沙箱(串(“四”));
      
      std::cout你指的是一些已经消失的东西。以下方法可以奏效

      #include <string>
      #include <iostream>
      
      class Sandbox
      {
      
      public:
          const string member = " "; //default to whatever is the requirement
          Sandbox(const string& n) : member(n) {}//a copy is made
      
      };
      
      int main()
      {
          Sandbox sandbox(string("four"));
          std::cout << "The answer is: " << sandbox.member << std::endl;
          return 0;
      }
      
      #包括
      #包括
      类沙箱
      {
      公众:
      const string member=“;//默认为任何要求
      沙盒(conststring&n):成员(n){}//创建了一个副本
      };
      int main()
      {
      沙箱沙箱(串(“四”));
      
      std::cout从其他答案可以清楚地看出,类成员不会在构造函数调用之外延长临时对象的生命。不过,在某些情况下,您的API可以“安全”地假设传递给类的所有
      常量和
      对象都不是临时对象,而是对范围良好的对象的引用

      如果您不想创建副本,您可以做些什么来确保UB不会潜入您的代码中?您拥有的最好工具是通过声明来维护传递给构造函数的
      std::string const&
      不是临时变量的假设