手动的内存管理通常被认为很麻烦且不利于程序的可维护性,modern C++ 采用智能指针的方式对内存进行动态管理,本文试图对智能指针做一个简单的入门介绍。

RAII 与智能指针

在《C++ 程序设计》一书中5.2.1提到,智能指针和资源管理息息相关,普通作用域里的变量依靠构造和析构函数完成了资源获取即初始化(RAII, Resource Acquisition Is Initialization),对于自由分配的对象,作用域为全局空间,标准库提供了智能指针来管理。

智能指针的核心原理如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
template <typename T>
class SmartPointer
{
public:
    explicit SmartPointer(T* p): p_(p) {} // explicit 避免由构造函数定义的隐式转换
    ~SmartPointer() { delete p_; }
    
private:
    T* p_;
}

将资源包在对象里,并在对象的析构函数中释放资源,以此确保资源不会因为被遗忘而丢失。

unique_ptr

unique_ptr 通过持有指针管理相应的对象,在 unique_ptr 作用域结束时释放资源,通常在两种情况调用对应的 deleter:

  • unique_ptr对象消亡
  • unique_ptr被另一个指针通过 operator=reset() 赋值。

shared_ptr

引用计数通过指针去管理控制块,一个控制块存放了引用计数、weak_ptr的数量、删除器、分配器等。做到多个shared_ptr之间的计数能共享,同步更新。比如:

1
2
3
4
5
shared_ptr<A> sp1 = make_shared<A>();
...
shared_ptr<A> sp2 = sp1;
...
shared_ptr<A> sp3 = sp1;

sp2 这样也能感知到 sp3 带来的引用计数的变化。

参考