为何不能用同一裸指针初始化两个不同的shared_ptr?
先看你的问题代码:
#include<iostream> #include<memory> using namespace std; class Base; class Base { public: int i; int j; Base(int _i, int _j) : i(_i), j(_j) {}; }; int main(void) { Base* q = new Base(5, 9); cout << q->i << endl; shared_ptr<Base> p(q); cout << p->j << endl; shared_ptr<Base> t(q); // mark cout << p.use_count() << endl; // cout << t.use_count() << endl; return 0; }
问题原因拆解:
shared_ptr的引用计数不是绑定在原始指针上,而是绑定在控制块里。当你用原始指针q创建第一个shared_ptr p时,会自动为q指向的对象生成一个控制块,里面的引用计数初始化为1。- 当你再用同一个
q创建第二个shared_ptr t时,t无法感知到已经存在的控制块,它会重新创建一个完全独立的控制块,这个新控制块的引用计数也是1。现在就有两个控制块同时盯着同一块内存。 - 程序结束时,
p和t会依次被销毁:各自的控制块会把引用计数减到0,然后各自执行delete q。这就导致了同一块内存被重复释放,直接触发崩溃。而p.use_count()只统计自己控制块里的计数,所以输出1,不是你预期的2。
为什么改成shared_ptr t(p)就正常?
当你用p来初始化t时,调用的是shared_ptr的拷贝构造函数,它会直接复用p的控制块,把控制块里的引用计数加1。此时p和t共享同一个控制块,引用计数变成2。当它们销毁时,各自把计数减1,直到最后一个shared_ptr销毁时,才会执行一次delete操作,不会重复释放内存,所以程序运行正常。
内容的提问来源于stack exchange,提问作者OnePie
相关产品推荐
相关产品推荐

