shared_ptr

shared_ptr 允许多个 shared_ptr 共同管理一个指针,每个 shared_ptr 的存在都会增加引用计数
初始化 shared_ptr

  1. // 1. 使用指针来初始化,p 是 A* 类型的
  2. std::shared_ptr<A> q(p);
  3. // 2. 通过其他 shared_ptr 来初始化,p 也是 shared_ptr
  4. std::shared_ptr<A> q(p);

错误的初始化方式

  1. // p 是指针类型 A*
  2. std::shared_ptr<A> q = p;

如何共享

  1. // 1. 通过初始化来共享,p 是 shared_ptr
  2. std::shared_ptr<A> q(p);
  3. // 2. 通过赋值来共享,如果 q 原来有指向,则原本引用计数 -1
  4. q = p;

weak_ptr

为什么要有 weak_ptr
shared_ptr 在两个对象都有成员变量指向对方时,会因为“死锁”而内存泄漏:

  1. struct A {
  2. std::shared_ptr<B> b_in_A;
  3. };
  4. struct B {
  5. std::shared_ptr<A> a_in_B;
  6. };
  7. int main() {
  8. std::shared_ptr<A> a(new A()); // a 的引用计数为 1
  9. std::shared_ptr<B> b(new B()); // b 的引用计数为 1
  10. a.b_in_A = b; // b 的引用计数为 2
  11. b.a_in_B = a; // a 的引用计数为 2
  12. return 0;
  13. }

weak_ptr 不增加引用计数

初始化方法:只能通过 shared_ptr 来初始化

对上述情形的改造方法:

  1. struct A {
  2. std::weak_ptr<B> b_in_A;
  3. };
  4. struct B {
  5. std::shared_ptr<A> a_in_B;
  6. };
  7. int main() {
  8. std::shared_ptr<A> a(new A()); // a 的引用计数为 1
  9. std::shared_ptr<B> b(new B()); // b 的引用计数为 1
  10. a.b_in_A = b; // b 的引用计数为 1
  11. b.a_in_B = a; // a 的引用计数为 2
  12. return 0;
  13. }

weak_ptr 使用需要注意:由于不增加引用计数,不知道内存释放已经被释放,所以不支持 ->* 运算符。通过 expire() 方法可以判断指针是否有效,然后通过 lock() 生成一个新的 shared_ptr 来使用。(也可以直接使用 lock() 来判断指针是否有效)

  1. std::shared_ptr<A> p(new A());
  2. std::weak_ptr<A> q(p);
  3. if (std::shared_ptr<A> t = q.lock()) {
  4. // do something with t
  5. }

unique_ptr

unique_ptr 要有智能指针独占指针

初始化:智能通过指针 A* 来初始化
拷贝:不支持拷贝,除非是函数返回时
释放

  • release() 释放指针的所有权,将智能指针置为空,不会释放内存
  • reset() 释放内存,将智能指针置为空