shared_ptr,weak_ptr,unique_ptr

来源:互联网 发布:sql的exists 编辑:程序博客网 时间:2024/06/05 20:11

1.shared_ptr 互相引用会出现资源不释放的问题,造成内存泄漏。

比如这段代码:

class C2;class C1 {private:std::shared_ptr<C2> _c2;  public:void setC2(std::shared_ptr<C2> c2) {_c2 = c2;}~C1() {std::cout << "kill c1\n";}};class C2 {private:std::shared_ptr<C1> _c1;public:void setC1(std::shared_ptr<C1> c1) {_c1 = c1;}~C2() {std::cout << "kill c2\n";}};void testptr(){std::shared_ptr<C1> c1(new C1());std::shared_ptr<C2> c2(new C2());if (c1 && c2){c1->setC2(c2);c2->setC1(c1);}

这个问题并不直观。

换一种思考方式,假设在某一个时刻,智能指针中的C1对象被销毁,那么c1._c2才会销毁,这个时候引用了C2类型的shared_ptr引用计数才会有可能变成0(按照我们的例子,就是在这个时刻引用计数变成0),智能指针中的C2对象才会被销毁,而也只有在智能指针中的C2对象被销毁时,引用了C1类型的shared_ptr引用计数才会变成0,这个时候才会去析构智能指针中的C1对象,所以分析到这里,我们会发想刚才的假设不会发生。这样就形成了一个互相牵制的死结。

两种解决方案:

1.如果确实需要按照testptr函数中的方式调用,则根据业务理清两个类的关系,哪个类生命周期依赖另一个,将命长的那个类作为shared_ptr作为命短的类的成员,将命短的那个类作为wead_ptr作为命长的类的成员,并在使用的时候,通过wead_ptr::lock()得到shared_ptr,保证使用范围内,命短的成员不会挂掉。

2.避免testptr函数中的调用方式,如果业务允许,可以考虑:

c1->setC2(c2);c2->setC1(c1_1);//std::shared_ptr<C1> c1_1(new C1());
weak_ptr并不像shared_ptr一样维护引用计数,所以不会存在像shared_ptr的问题,但是引入的新问题是,如果使用weak_ptr,即便是你定义了一个变量,这个变量的存活期也并不能由你来掌控,所以是一个弱控制的指针,只有在调用lock拿到一个shared_ptr的这段时间里,是你可以确定你的变量是真实存活着的。并且weak_ptr并不能单独使用,只能配合shared_ptr或者其他weak_ptr一同使用,来解决shared_ptr互相引用的问题。

unique_ptr旨在替代auto_ptr,因为auto_ptr的copy导致的被copy对象变成null的问题,整体用法就是提供对内存对象的独占访问,并且使用release显式移交所有权。

0 0
原创粉丝点击