文章目录

  • 概述
  • shared_ptr使用


概述

指针让我们在域边界之外拥有reference语义,然而,确保“pointer的寿命”和“其所指对象的寿命”一致却是件棘手的事。
C++11提供两大类型智能指针:shared_ptr和unique_ptr。

  • shared_ptr实现共享式拥有的概念。多个shared_ptr指向同一个对象,当最后一个shared_ptr析构时,指向的对象也被释放,标准库还提供weak_ptr, bad_weak_ptr, enable_shared_from_this等辅助类。
  • unique_ptr实现独占式拥有的概念。保证同一时间内只有一个指针指向对象,你可以移交所有权。

shared_ptr使用

shared_ptr的目标就是在其所指的对象不再被需要后,自动释放与之相关的资源。
构造:

shared_ptr<string> pStr1(new string("abc"));
shared_ptr<string> pStr2 = make_shared<string>("abc");

其中模板参数类型是指针指向的数据类型。
接受单一指针的构造函数是explicit的,因此不能进行隐式转换

shared_ptr<string> pStr = new string("abc");  // ERROR
shared_ptr<string> pStr{new string("abc")};  // OK

你也可以先声明shared_ptr再赋值一个指针给它。

shared_ptr<string> pStr;
pStr.reset(new string("abc"));
pStr = new string("abc"); // ERROR

你可以像使用指针一样使用shared_pointer

pStr->replace(0, 1, "J);
(*pStr)[0] = 'N';  // 改变string第一个元素

容器总是为传入的元素创建属于容器自己的拷贝,因此当把同一个shared_ptr重复添加到vector中时,多个shared_ptr将指向同一个string对象,当最后一个shared_ptr销毁时,会对其指向的对象调用delete
然而对于array,我们应该调用的是delete[],而不是delete,因此创建一个指向array的shared_ptr是错误的

shared_ptr<int> p(new int[10]); // ERROR

我们在第二个参数指定deleter

shared_ptr<int> p(new int[10], [](int*p) { delete[] p; });
shared_ptr<int> p(new int[10], std::default_delete<int[]>()); // default_delete默认调用delete[]

C++17之前,只有unique_ptr支持数组类型的模板

unique_ptr<int[]> p(new int[10]); // 正确。并且能够正确调用delete[]
shared_ptr<int[]> p(new int[10]); // 编译错误

C++17之后,shared_ptr也支持数组类型的模板,并且也可以像原生数组一样取数组元素

shared_ptr<int[]> p(new int[10]); // C++17以后正确
p[0] = 0; // C++17之后正确
p->get()[1] = 1; // C++11不支持operator[]可使用此写法,与上述语句等价

注:本人在visual studio上使用shared_ptr<int[]> p(new int[10]);没有检测到内存泄漏,可能是vs进行了优化?

参考:

  1. https://stackoverflow.com/questions/13061979/can-you-make-a-stdshared-ptr-manage-an-array-allocated-with-new-t