C++11 引入了 3 个智能指针类型:
std::unique_ptr<T> :独占资源所有权的指针;std::shared_ptr<T> :共享资源所有权的指针,它的原理是使用引用计数实现对同一块内存的多个引用,在最后一个引用被释放时,指向的内存才释放;std::weak_ptr<T> :共享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。
1. std::unique_ptr
{
std::unique_ptr<int> uptr = std::make_unique<int>(200);
std::unique_ptr<int> uptr1 = uptr;
std::unique_ptr<int> uptr2 = std::move(uptr);
assert(uptr == nullptr);
}
2. std::shared_ptr
{
std::shared_ptr<int> sptr = std::make_shared<int>(200);
assert(sptr.use_count() == 1);
{
std::shared_ptr<int> sptr1 = sptr;
assert(sptr.get() == sptr1.get());
assert(sptr.use_count() == 2);
}
assert(sptr.use_count() == 1);
}
错误用法1:退出{ } p1、p2都会对p0析构,导致p0被删除两次,报错;
{
int *p0 = new int(1);
shared_ptr<int> p1(p0);
shared_ptr<int> p2(p0);
}
错误用法2:循环引用;
struct Father{
shared_ptr<Son> son_;
};
struct Son{
shared_ptr<Father> father_;
};
int main(){
auto father = make_shared<Father>();
auto son = make_shared<Son>();
father->son_ = son;
son->father_ = father;
return 0;
}
main 函数退出之前,Father_obj 、Son_obj 的引用计数都是 2 ,退出main 后,引用计数为1 ,导致对象没法被销毁,从而引起内存泄漏。
3. std::weak_ptr
std::weak_ptr 为弱引用指针(std::shared_ptr 是强引用指针),弱引用指针不会增加引用计数。 使用std::weak_ptr 修正错误用法2:
struct Father{
shared_ptr<Son> son_;
};
struct Son{
weak_ptr<Father> father_;
};
int main(){
auto father = make_shared<Father>();
auto son = make_shared<Son>();
father->son_ = son;
son->father_ = father;
return 0;
}
- 退出
main 之前,Son_obj 引用数为2 ,Father_obj 引用为1 ; - 退出
main 后,son 指针被销毁 ? Son_obj 引用数为1; ??????father 指针被销毁 ? father_obj 引用数为0 ; father_obj 引用数为0 ? Father_obj 被析构 ? Father_obj.son 被销毁? Son_obj 引用数为0 ? Son_obj 被析构;- 最终
father_obj 与Son_obj 被正常析构。
|