概述
shared_ptr和weak_ptr是从C++11标准库Boost中引入的两种智能指针目前在实际应用最为广泛。此外。Boost库还提出了boost::scoped_ptr、boost::scoped_array、boost::instrusive_ptr等智能指针,虽然尚未得到C++标准采纳,但是在开发实践中可以使用。
shared_ptr
-
shared_ptr对象除了包括一个所拥有对象的指针外,还必须包括一个引用计数代理对象的指针。
-
时间上的开销主要在初始化和拷贝操作上,*和->操作符重载的开销跟auto_ptr是一样的。
-
开销并不是我们不使用shared_ptr的理由,永远不要进行不成熟的优化,直到性能分析器告诉你这一点。
Tip:实际应用中我总是谁持有这个指针则用shared_ptr。
weak_ptr
为了解决这样一个问题而引入的:
在 Man 类内部会引用一个 Woman,Woman 类内部也引用一个 Man。当一个 man 和一个 woman 是夫妻的时候,他们直接就存在了相互引用问题。man 内部有个用于管理wife生命期的 shared_ptr 变量,也就是说 wife 必定是在 husband 去世之后才能去世。同样的,woman 内部也有一个管理 husband 生命期的 shared_ptr 变量,也就是说 husband 必须在 wife 去世之后才能去世。这就是循环引用存在的问题:husband 的生命期由 wife 的生命期决定,wife 的生命期由 husband 的生命期决定,最后两人都死不掉,违反了自然规律,导致了内存泄漏。
一般来讲,解除这种循环引用有下面三种可行的方法:
-
当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
-
当 parent 的生存期超过 children 的生存期的时候,children 改为使用一个普通指针指向 parent。
使用弱引用的智能指针打破这种循环引用
weak_ptr 对象引用资源时不会增加引用计数,但是它能够通过 lock() 方法来判断它所管理的资源是否被释放。做法就是上面的代码注释的地方取消注释,取消 Woman 类或者 Man 类的任意一个即可,也可同时取消注释,全部换成弱引用 weak_ptr。
Tip:实际应用中我总是保持着只有一个shared_ptr的原则,其他就都是使用weak_ptr