我正在使用一个库,该库可以导出如下功能:
// there is some type T
std::shared_ptr<T> foo(params);
,并且以下代码可以正常运行:
auto p = foo(params);
auto & v0 = *p;
// use v0 as a T's reference
以下崩溃:
auto & v1 = *foo(params);
// use v1 as a T's reference
那么v0
和v1
有什么区别?非常感谢您的帮助。
答案 0 :(得分:9)
shared_ptr
所指向的对象仅在存在至少一个仍然指向它的一个共享指针时才存在。
在您的示例中,可能只有一个这样的指针,并且它由foo
返回。
对于v0
,p
成为shared_ptr
,使对象保持活动状态。
对于v1
,只有一个临时共享指针仅在v1
初始化期间存在。在您使用引用时,指向的指针和对象已消失,在使用时使其成为悬垂的指针。
答案 1 :(得分:3)
声明
auto & v1 = *foo(params);
是潜在的未定义行为。
函数foo
可能在内部构造了一个std::shared_ptr
并将其作为临时对象(技术上是 prvalue )返回给调用者,该对象应该分配给某个变量
您没有将表达式的智能指针分配给任何变量。但是,您要抓取指向的对象(使用*
运算符),并将其分配给引用v1
。
在表达式求值结束时,临时std::shared_ptr
将被销毁,并且(作为智能指针)该对象也将被指向。
因此,auto & v1
指的是被破坏的对象,对其的访问是未定义的行为(在大多数情况下会产生分段错误)。
答案 2 :(得分:1)
在您的第一个示例中,p
保留在范围内,保留对该对象的引用,从而使该对象保持活动状态。在第二个示例中,shared_ptr
在创建v1
之后被销毁,销毁了对象(假定它是唯一的引用),并使v1
指向未分配的内存。