引用可以延长由 mamber 函数返回的 class 的任何成员数据的生命周期吗

Can a reference prolong the lifetime of any member data of a class which is returned by a mamber function

class sample
{
  std::string mString;

public:
  void Set(const std::string &s)
  {
    mString = s;
  }

  //std::string Get() const
  const std::string& Get() const
  {
    return mString;
  }
};

假设我有一个如上所述的 class,现在我这样使用 class:

sample *p = new sample;
p->Set("abcdefg");
const std::string& ref = p->Get();
delete p;
p = nullptr;
std::cout << ref << std::endl;

如你所见,成员函数Getreturns一个引用,它赋给了外部引用ref。之后,整个对象被删除。

不过,这段代码似乎没有任何错误。

我有点困惑。它可能 运行 只是因为我很幸运,或者它的引用 ref 延长了成员变量的生命周期 mString?

否,通过引用绑定延长生命周期仅适用于从纯右值具体化的临时对象。

使用 new 创建的对象的生命周期永远不会超过 delete

您在这里看到的只是未定义行为的表现。 refdelete p; 之后悬空,因此在 cout 语句中读取它具有未定义的行为。


如果 Get 是 returning by-value (std::string Get() const),那么临时从函数的生命周期将延长至引用 ref.

的生命周期

在这种情况下,程序行为将是 well-defined。


同样,如果 sample 对象具有自动存储持续时间,则引用不会延长其生命周期或其子对象之一的生命周期:

/* DO NOT USE: Undefined behavior */

const std::string& ref = []() -> const std::string& {
    sample s;
    p.Set("abcdefg");
    return s->Get();
    // lifetime of s ends with function returning
}();

/* UNDEFINED BEHAVIOR */    
std::cout << ref << std::endl;

这是 lambda 的 return 类型,需要将其从 const std::string& 更改为 std::string 以避免 UB。只有第一个引用绑定可以延长生命周期,因此在这种情况下更改 Get 的 return 类型是不够的。