[c++11]智能指针类型

参考:Smart Pointers (Modern C++)

使用原始指针需要手动操作内存分配和删除,同时需要密切关注指针引用。在现代C++编程中,标准库包括智能指针(smart pointer),用于确保程序不受内存(free of memory)和资源泄漏(resource leaks)的影响,并且是异常安全(exception-safe)的

头文件

智能指针的声明位于头文件<memory>

原理

C++没有单独的垃圾收集器(garbage collector)在后台运行,是通过标准C++范围规则(scoping rule)来管理内存,以便运行时环境更快、更高效

智能指针是在栈上声明的类模板,通过使用指向堆分配对象的原始指针进行初始化。智能指针初始化后,它拥有原始指针。这意味着智能指针负责删除原始指针指定的内存。智能指针析构函数包含对delete的调用,并且由于智能指针在栈上声明,因此当智能指针超出作用域时将调用其析构函数,即使在栈上的某个位置引发异常

使用熟悉的指针运算符->*访问封装的指针,智能指针类重载这些运算符以返回封装的原始指针

类别

学习3种不同的智能指针:

  • unique_ptr
  • shared_ptr
  • weak_ptr

编程规范

智能指针对原始指针进行了封装,能够保证其安全使用,与此同时也造成了效率的小小降低

  • 大多数情况下,当初始化原始指针或资源句柄以指向实际资源时,立即将指针传递给智能指针
  • 原始指针只用于有限范围、循环或辅助函数的小代码块中。在这些代码块中,性能至关重要,并且不可能混淆所有权
  • 始终在单独的代码行上创建智能指针,而不是在参数列表中,这样就不会由于某些参数列表分配规则而发生细微的资源泄漏

使用智能指针的基本步骤如下:

  1. 声明智能指针作为自动(automatic)或局部(local)变量(不要对智能指针使用newmalloc表达式)
  2. 在类型参数中,指定封装指针的指向类型
  3. 在智能指针构造函数中传递原始指针(已指向对象)(一些实用程序函数或智能指针构造函数可以辅助执行此操作)
  4. 使用重载的*->运算符访问对象
  5. 让智能指针删除对象

示例

创建结构体S,分别使用原始指针rptr和智能智能sptr创建对象,输入函数print进行打印

struct S {
    S(char a, int b) : a(a), b(b) {}

    char a;
    int b;
};

void print(const struct S &ptr) {
    cout << ptr.a << " " << ptr.b << endl;
}

int main(int argc, char *argv[]) {
    std::unique_ptr<struct S> sptr(new struct S('b', 3));
    auto *rptr = new struct S('b', 3);

    print(*sptr);
    print(*rptr);

    delete (rptr);
}