我对智能指针相当陌生,我不能理解我下面附上的代码的结果。基本上,在传递给另一个unique_ptr
对象后,shared_ptr
对象的引用计数和原始指针本身会发生变化。
代码是这样的
typedef shared_ptr<int> sp;
class bar {
public:
const sp& x; // line 3: if change this line to "const sp x;" then it's fine
bar(const sp xx) : x(xx) {
cout << "bar: count=" << x.use_count() << "; addr=" << x.get() << endl;
}
void test() {
cout << "test: count=" << x.use_count() << "; addr=" << x.get() << endl;
}
};
int main() {
auto p = make_shared<int>(0);
auto b = make_unique<bar>(p);
b->test();
}
如果我编译并运行代码,它打印出:
bar: count=2; addr=0x557c8b02dec0
test: count=1224736736; addr=0x7ffdb5cbd5c0
所以refcount和指针都被改变了。它看起来像是某个未初始化的值
但是如果我把第3行改为const sp x;
,那么两个值看起来都很正常:
bar: count=3; addr=0x5590f026eec0
test: count=2; addr=0x5590f026eec0
很抱歉,因为这是一个快速的最低限度的情况下,我想出了解决我的问题。我觉得这与unique_ptr
的工作方式有关,但我不确定。
谁能给我点光,帮助我理解为什么代码是这样的?
感谢此处:
const sp& x;
bar(const sp xx) : x(xx)
将共享指针赋值给局部变量xx
,然后将const引用x
绑定到局部变量。当构造函数结束它的运行时,该局部变量将超出作用域,给您留下对Eldritch Horrors和未定义行为的引用。
为了解释你关于删除&
的观察:
删除&
可以防止这种情况,因为在这种情况下,你只是将共享指针直接分配给x
,从此不再依赖于局部变量xx
,因此不受其超出作用域的影响。
扩展:如果你想保存一个引用,你可以做的另一件事是设置xx
为引用本身(即bar(const sp& xx) : x(xx)
);在本例中,您将把x
绑定到p
。