智能指针

有三个智能指针,auto_ptr(弃用)、unique_ptr、shared_ptr.
智能指针可以自动跟踪动态内存,在其过期时自动释放。

#include<memory>

一、shared_ptr

用于new创建的对象,而不适用于new[]创建的对象,
用于多个指针共享一个地址的情况。
默认初始化的智能指针中保存着一个空指针。

1.1 make_shared函数

最安全的分配和使用动态内存的方法是调用make_shared函数;
通常使用auto定义一个对象来保存make_shared的结果,
注意,auto只能用来初始化单个值,因此不能用来初始化列表。

auto p=make_shared<int>(42);//p指向的对象只有p一个引用者
auto q(p);//p和q指向相同的对象,此对象有两个使用者。

不能将一个内置指针隐式转化为一个智能指针:

shared_ptr<int>p1=new int(1024);//错误,必须使用直接初始化方式
shared_ptr<int>p2(new int(1024));//正确,使用了直接初始化方式

1.2 智能指针不能使用动态生存期资源的类:

  1. 程序不知道自己需要使用多少对象;
  2. 程序不知道所需对象的准确类型;
  3. 程序需要在多个对象之间共享数据。

1.3 智能指针使用规范

  1. 不使用相同的内置指针值初始化(或reset)多个智能指针;
  2. 不delete get()返回的指针;
  3. 不使用get()初始化或reset另一个智能指针;
  4. 如果你使用get返回的指针,记住当最后一个对应的指针销毁后,你的指针就变为无效了;
  5. 如果你使用智能指针管理的资源不是new分配的内存,记住传递给他一个删除器。

二、unique_ptr

用于只存留一个指针指向最后地址的情况,同时unique_ptr有指向new[]的版本。
控制权转移。

unique_ptr必须使用直接初始化方式:

unique_ptr<double> p1;
unique_ptr<int> p2(new int(42));

unique_ptr的“独占”是指:不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr。例如:

std::unique_ptr<int> p (new int);
std::unique_ptr<int> q = p; //error

但是unique_ptr允许通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,注意,这时它本身就不再拥有原来指针的所有权了。

std::unique_ptr<int> p (new int);
std::unique_ptr<int> q = std::move(p); //ok

三、操作

3.1 shared_ptr和unique_ptr都支持的操作

操作 作用
shred_ptrsp,unique_ptrup 空智能指针,可以指向类型为T的对象
p->mem 等价于(*p).mem
p.get() 返回p中保存的指针
swap(p,q),p.swap(q) 交换p和q中的指针

3.2 shared_ptr中独有的操作

操作 作用
make_shared(args) 初始化一个智能指针
shared_ptrp(q) 使用q初始化p,会增加计数
p=q q必须能转化为shared_ptr类型
p.uniqe() 判断计数是否为1,是1返回true
p.use_count() 返回与p共享对象的智能指针数量

3.3 unique_ptr中独有的操作

操作 作用
unique_ptr(T) u1 , unique_ptr(T,D)u2 空智能指针,u1使用delete释放指针,u2使用D释放指针
unique_ptr(T,D)u(d) 空指针,使用类型为D的对象d代替delete
u=nullptr 释放u指向的对象,将u置为空
u.release() 释放u的控制权,将u置为空
u.reset() 释放u指向的对象
u.reset(q),u.reset(nullptr) 如果提供了内置指针q,令u指向这个对象;否则将u置为空

四、weak_ptr

弱指针用于避免share_ptr循环引用的问题。
由于弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。
虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题。

五、动态数组

大多数情况下使用动态数组都是使用vector来实现。
标准库提供了一个可以管理new分配的数组的unique_ptr版本。

unique_ptr<int[10]>up(new int [10]);//初始化
up.release();//自动用delete[]销毁其指针

5.1 allocator类

TODO:)

其他

如ps是一个智能指针对象,则可以对它:

解除引用*ps
访问结构成员ps->index
将它赋给同类型常规指针

unique_ptr为右值时,可将其赋给shared_ptr
unique_ptr赋给另一个unique_ptr时,需要使用移动构造函数std::move()

参考链接:
https://www.cnblogs.com/wuyepeng/p/9741241.html
https://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html

原文地址:https://www.cnblogs.com/chendeqiang/p/12861555.html