c++ shared_ptr引用计数在传递给unique_ptr对象后发生更改

n3ipq98p  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(125)

我对智能指针还是个新手,我不理解下面附的代码的结果。基本上,shared_ptr对象的引用计数和原始指针本身在传递给另一个unique_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

所以引用计数和指针都改变了,看起来像是一些未初始化的值。
但是如果我把第3行改成const sp x;,那么两个值看起来都正常:

bar:  count=3; addr=0x5590f026eec0
test: count=2; addr=0x5590f026eec0

很抱歉使用了错误的命名,因为这是我为解决我的问题而提出的一个快速的最小情况。我觉得这与unique_ptr的工作原理有关,但我不确定。
有人能给我一些启发,帮助我理解为什么代码会这样吗?
谢谢

c9qzyr3d

c9qzyr3d1#

此处:

const sp& x;                                                           
bar(const sp xx) : x(xx)

将共享指针赋给一个局部变量xx,然后将常量引用x绑定到 * that * 局部变量,当构造函数结束运行时,该局部变量将超出作用域,留下对Eldritch Horrors的引用和未定义的行为。
要解释您关于删除&的观察结果:
删除&可以防止这种情况发生,因为在这种情况下,您只需将共享指针直接赋给xx从此不再依赖于局部变量xx,因此不会受到其超出范围的影响。
扩展:如果你想保存一个引用,你可以做的另一件事是将xx设置为引用本身(即bar(const sp& xx) : x(xx));在本例中,您将绑定xp

相关问题