引用可以延长由 mamber 函数返回的类的任何成员数据的生命周期吗
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,通过引用绑定的生命周期扩展仅适用于从纯右值具体化的临时对象。
使用
new
创建的对象的生命周期永远不会超过delete
。您在这里看到的只是未定义行为的表现。
ref
在delete p;
之后悬空,因此在cout
语句中读取它具有未定义的行为。如果
Get
按值返回 (std::string Get() const
),那么从函数的返回值中具体化的临时值确实会具有它的生命周期延长到了引用ref
的生命周期。在这种情况下,程序行为将被明确定义。
同样,如果
sample
对象具有自动存储持续时间,则引用不会延长其生命周期或其子对象之一的生命周期:这里是 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 pastdelete
.What you are seeing here is just a manifestation of undefined behavior.
ref
is dangling afterdelete p;
and therefore reading from it in thecout
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 referenceref
.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:Here it is the lambda's return type that would need to be changed from
const std::string&
tostd::string
to avoid the UB. Only the first reference binding can extent lifetime and therefore changing the return type ofGet
would not be sufficient in this case.