浅谈智能指针

前情提要

野指针(Wild Pointer): 野指针是指指向任意未知位置的指针,它没有被初始化或者指向无效的内存。

悬挂指针(dangling pointer):指指向已释放或无效内存的指针。当一个指向动态分配内存的指针所指向的内存被释放后,该指针仍然保留着原来的指向,但此时使用该指针访问所指向的内存将导致未定义的行为。

RAII (Resource Acquisition Is Initialization): 资源获取即初始化, R使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。像下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class str_ {
public:
str_() { data = new char[1024]; }
~str_() { delete data; }
private:
char* data_{ nullptr };
}

int main() {
auto pdata = new char[1024]; // 这样的做法容易漏掉delete,导致内存泄漏
delete[] pdata;

/*
这样当我们在一个函数内部使用局部变量,当退出了这个局部变量的作用域时,这个变量也就被毁了;当这个变量是类对象时,这个时候,就会自动调用这个类的析构函数,而这一切都是自动发生的,不要程序员显式调用完成。
*/
{
str_ data;

}
}

智能指针

因为C++使用内存的时候很容易出现野指针、悬空指针、内存泄露等问题。所以C++11引入了智能指针来管理内存。使用智能指针(如std::unique_ptrstd::shared_ptr)来自动管理资源生命周期,避免手动释放内存和引入悬垂指针和野指针问题。共有四种智能指针:

  • auto_ptr:已经不用了
  • unique_ptr:独占式指针,同一时刻只能有一个指针指向同一个对象
  • shared_ptr:共享式指针,同一时刻可以有多个指针指向同一个对象
  • weak_ptr:用来解决shared_ptr相互引用导致的死锁问题

总的来说,智能指针是一个RAII类模板,用于动态分配内存,其设计思想是将基本类型指针封装为(模板)类对象指针,并在离开作用域时调用析构函数,使用delete删除指针所执行的内存空间。

  • unique_ptr:

    • 独占式指针,与所指对象的内存绑定紧密,禁止其他智能指针与其他共享同一个对象。也就是同一时间只能有一个智能指针可以指向该对象

    • 独占的意思是不可以复制(拷贝构造和拷贝复制),但是我们可以利用std::move将其转移给其他unique_ptr(可以移动构造和移动赋值)。一旦转移,这个所有权就会失去,除非被显示归还

    • 从实现上来讲,unique_ptr是一个删除了拷贝构造函数,保留了移动构造函数的指针类型。可以使用右值对unique_ptr进行构造

  • shared_ptr

    • 实现了共享式拥有的概念,即多个智能指针可以指向相同的对象,该对象以及相关资源会在其所指对象不再使用之后,自动释放与对象相关的资源
    • 它是使用计数机制来表明资源被几个指针共享

    • 可以通过成员函数 use_count() 来查看资源的所有者个数,除了可以通过 new 来构造,还可以通过传⼊auto_ptr,unique_ptr,weak_ptr 来构造。当我们调⽤ release() 时,当前指针会释放资源所有权,计数减⼀。当计数等于 0时,资源会被释放。

  • weak_ptr,解决shared_ptr相互引用的问题,两个指针的引用计数永远不会下降为0,从而导致死锁问题。而weak_ptr是对对象的一种弱引用,可以绑定到shared_ptr,但不会增加对象的引用计数。

    • weak_ptr是为了配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能智能,因为它没有普通指针的行为,没有重置*和→。它得最大作用是协助shared_ptr工作,像是旁观者那样观测资源的使用情况

    • weak_ptr是一种不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象。进行该对象的内存管理的是那个强引用的shared_ptr

    • weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr设计的目的是为了配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它只可以从一个 shared_ptr 或另⼀个 weak_ptr 对象构造,,它的构造和析构不会引起引用计数的增加或者减少