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

发布于 2025-01-12 19:21:11 字数 647 浏览 2 评论 0原文

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;
  }
};

假设我有一个像上面这样的类,现在我像这样使用这个类:

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

如您所见,成员函数 Get 返回一个引用,该引用被分配给外部引用 ref.之后,整个对象被删除。

然而,这段代码似乎可以正常工作,没有任何错误。

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

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;
  }
};

Let's say I have such a class as above and now I use this class like this:

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

As you see, the member function Get returns a reference, which is assigned to the outer reference ref. After that, the whole object is deleted.

However, it seems that this code works without any error.

I'm a little confused. It could run just because I'm lucky or it's the reference ref that prolongs the lifetime of the member variable mString?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野鹿林 2025-01-19 19:21:11

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

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

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


如果 Get 按值返回 (std::string Get() const),那么从函数的返回值中具体化的临时值确实会具有它的生命周期延长到了引用ref的生​​命周期。

在这种情况下,程序行为将被明确定义。


同样,如果 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 的返回类型,需要从 >const std::string&std::string 以避免 UB。只有第一个引用绑定可以延长生存期,因此在这种情况下更改 Get 的返回类型是不够的。

No, lifetime extension by reference binding applies only to temporary objects materialized from prvalues.

Objects created with new never have their lifetime extended past delete.

What you are seeing here is just a manifestation of undefined behavior. ref is dangling after delete p; and therefore reading from it in the cout statement has undefined behavior.


If Get was returning by-value (std::string Get() const), then it would be true that the temporary materialized from the return value of the function would have its lifetime extended to that of the reference ref.

And in that case the program behavior would be well-defined.


Similarly if the sample object had automatic storage duration, the reference would not extent its lifetime or the lifetime of one of its subobjects either:

/* 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;

Here it is the lambda's return type that would need to be changed from const std::string& to std::string to avoid the UB. Only the first reference binding can extent lifetime and therefore changing the return type of Get would not be sufficient in this case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文