美文网首页
Effective c++学习笔记(item13的引申:RCSP

Effective c++学习笔记(item13的引申:RCSP

作者: 懒生活 | 来源:发表于2021-10-20 19:43 被阅读0次

Effective c++学习笔记(item13的引申:RCSP can't break cycles of references)

RCSP: 是应用计数smart pointer的缩写。引用计数智能指针实际就是std::shared_ptr,在遇到循环引用的时候是会有问题的。书中item13中只是这么一句说明,没有额外查资料估计也就不了了之了。

1 什么是循环引用

这里重点描述下循环引用的场景和解决方法。

  1. 考虑以下的代码,为什么在智能指针离开作用域后没有自己释放。
class CA;
class CB;
class CA{
public: 
~CA(){count<<"release CA"<<endl;}
shared_ptr<CB> AsCB;
};
class CB{
public: 
~CB(){count<<"release CB"<<endl;}
shared_ptr<CA> BsCA;
};
void testCircleofReference()
{
    shared_ptr<CA> a(new CA);
    shared_ptr<CB> b(new CB);
    a->AsCB = b;
    b->BsCA = a;
}
int main()
{
    testCircleofReference();
}

在testCircleofReference函数中,shared_ptr<CA> a(new CA);语句会让RCSP a的引用计数+1, b->BsCA = a;这个语句也会让a的引用计数+1(其实此时b->BsCA的引用计数和a的引用计数是共享的都是2。当testCircleofReference函数执行完毕后,因为a,b都离开了作用域,所以引用计数都会-1,但此时还各自有一次的引用计数,所以,智能指针a虽然释放了,但a关联的资源(new CA)不会释放,执行的表现就是没有调用CA的析构函数。

  1. 考虑下面的代码,为什么可以正确释放资源,下面的代码和上面的代码只差一行,因为这一行的注释,使得循环环断开了。
class CA;
class CB;
class CA{
public: 
~CA(){count<<"release CA"<<endl;}
shared_ptr<CB> AsCB;
};
class CB{
public: 
~CB(){count<<"release CB"<<endl;}
shared_ptr<CA> BsCA;
};
void testCircleofReference()
{
    shared_ptr<CA> a(new CA);
    shared_ptr<CB> b(new CB);
    a->AsCB = b;
    //b->BsCA = a;//这一注释使循环引用的环断开,不再存在循环引用
}
int main()
{
    testCircleofReference();
}

上述的代码在testCircleofReference函数执行完毕后,a,b因为离开作用域会释放掉。b的引用计数变为0,会触发资源CB的释放,CB的释放会触发成员对象BsCA的释放,此时a的引用计数会被-1,而变成0,从而又出发a所关联的资源释放。

weak_ptr的作用

weak_ptr就是若引用的意思,如果一个shared_ptr赋值给weak_ptr,引用计数不变化。稍微调整下上面的例子,得到新的例子:

class CA;
class CB;
class CA{
public: 
~CA(){count<<"release CA"<<endl;}
weak_ptr<CB> AsCB;//通过weak_ptr打断循环引用
};
class CB{
public: 
~CB(){count<<"release CB"<<endl;}
shared_ptr<CA> BsCA;
};
void testCircleofReference()
{
    shared_ptr<CA> a(new CA);
    shared_ptr<CB> b(new CB);
    a->AsCB = b;//因为AsCB是weak_ptr,所以这句话的赋值不会让b的引用计数+1。
    b->BsCA = a;
}
int main()
{
    testCircleofReference();
}

在testCircleofReference函数运行之后,a,b因为离开作用域,引用计数会-1,此时关联CA的引用计数是1,关联CB的引用计数是0,所以会触发CB的释放,CB的释放导致CA的引用计数-1,变成0,从而又引发CA的资源释放。

尽量避免循环引用的情况

weak_ptr毕竟只是一个规避手段,我想最好的方式还是在设计阶段规避这种资源的循环引用。就像设计上一个不提倡循环依赖一样。

相关文章

网友评论

      本文标题:Effective c++学习笔记(item13的引申:RCSP

      本文链接:https://www.haomeiwen.com/subject/spfxaltx.html