智能指针

智能指针(Smart Pointer)是一种管理堆内存的智能方式,它通过重载运算符模拟普通指针的行为,但可以自动管理资源的释放。智能指针主要解决原始指针易导致的内存泄漏问题。

C++11中引入了三种智能指针:

  1. unique_ptr: 独占式拥有权的智能指针,采用独占/拷贝语义。
  2. shared_ptr: 共享式拥有权的智能指针,引用计数机制。
  3. weak_ptr: 弱引用指针,需要配合shared_ptr使用。

智能指针声明时需要包含头文件memory,并指定指针类型: 智能指针支持解引用操作符*和->来访问资源:

#include <memory>
std::unique_ptr<int> p1(new int(1));

当智能指针离开作用域时,会自动释放占有的内存。

独占式智能指针unique_ptr

auto p1 = std::make_unique<int>(1);
auto p2 = std::move(p1); // p1无效

auto p = p1.release(); //释放控制权
delete p; 

std::unique_ptr<int[]> arr(new int[10]);

shared_ptr实现共享式拥有权

auto p1 = std::make_shared<int>(10);
auto p2 = p1; //共享拥有权

p1.use_count() //引用计数
// p1.use_count() == 2

但是shared_ptr会有循环引用的问题,循环依赖主要发生在两个shared_ptr相互引用的情况下,示例代码如下:

struct A; 

struct B {
  shared_ptr<A> a;
  ~B() { cout << "B destructor" << endl; }  
};

struct A {
  shared_ptr<B> b; 
  ~A() { cout << "A destructor" << endl; }
};

int main() {
  shared_ptr<A> a = make_shared<A>();
  shared_ptr<B> b = make_shared<B>();
  
  a->b = b; 
  b->a = a;
}
// 在运行程序后,控制台不会打印任何消息,因为AB的析构函数都没有正确的执行

执行结果是A,B的析构函数都不会被调用,出现内存泄露。 分析原因如下:

struct A;

struct B {
  weak_ptr<A> a;
  
  ~B() { cout << "B destructor" << endl; }
}; 

struct A {
  shared_ptr<B> b;

  ~A() { cout << "A destructor" << endl; }  
};

int main() {
  shared_ptr<A> a = make_shared<A>();
  shared_ptr<B> b = make_shared<B>();

  a->b = b;
  b->a = a; 
}

weak_ptr没有自己的引用计数,它通过与shared_ptr关联来间接引用计数。 具体来说:

这使得weak_ptr可以安全地用于Break循环引用而不影响对象的生命周期。不过weak_ptr本身不增加引用计数。