C++11指针智能 - 常用知识点

RAII:使用类对象来管理指针,在类的构造函数里面将指针传入并保存在类成员,在类析构的时候将指针释放掉。那么当这个类对象是一个局部变量时,出了作用域就会被析构掉,从而释放指针。

(1)auto_ptr:
是一个类,类的构造函数将指针传入并保存,在类析构的时候将指针释放掉。
- 拷贝构造函数,将旧的auto_ptr里面的指针赋值给新的auto_ptr,然后将旧的auto_ptr里的指针置为null。
- 重载了赋值运算符:也会将被赋值的对象的指针给新的auto_ptr,然后将自己里面的指针置为null。
缺点:被拷贝的对象里面的指针为空,这样出错率比较高。

(2)scoped_ptr:
为了弥补auto_ptr的缺点,该指针将拷贝构造函数和赋值运算符重载变成了私有。
缺点:使用的局限性。

(3)shared_ptr:
使用引用计数来管理指针,在初始化、调用赋值运算符重载、拷贝构造都会导致引用计数+1,在对象释放后引用计数-1,当引用计数为0时,将内部的指针释放。
- make_shared要优于使用new,make_shared可以一次将需要内存分配好。
- std::shared_ptr的大小是原始指针的两倍,因为它的内部有一个原始指针指向资源,同时有个指针指向引用计数,引用计数是分配在动态分配的,std::shared_ptr支持拷贝,新的指针获可以获取前引用计数个数。
- shared_ptr.use_count():获取指针的引用个数
缺点:引用计数的缺点是相互引用,导致引用无法归零,始终不会释放内部的指针。这也是Java GC一般不采用引用计数算法的原因。

(4)weak_ptr:
weak_ptr被设计为与shared_ptr共同工作,解决share_ptr的互相引用导致的缺点。使用weak_ptr 来打破循环引用,它与一个 shared_ptr 绑定,但却不参与引用计数的计算,同时,在需要时,它还能摇身一变,生成一个与它绑定的 shared_ptr 共享引用计数的新 shared_ptr。
- std::weak_ptr w(sh):用一个shared_ptr初始化
- std::shared_ptr another = w.lock():变出 shared_ptr 
- bool isDeleted = w.expired():判断weak_ptr所观察的shared_ptr的资源是否已经释放

(5)unique_ptr:
只允许一个unique_ptr对象来管理指针。
- unique_ptr = std::move(unique_ptr):用来将指针的控制权转移给其他unique_ptr对象。
- unique_ptr.get():获取指针。
- unique_ptr.release():释放对指针的控制权,返回指针,但是不会对释放指针。
- unique_ptr.reset(pointer):其中参数是以个指针,作用是:先释放unique_ptr中现有的指针,然后将参数的指针交由这个unique_ptr管理。
- unique_ptr.swap(unique_ptr):将两个unique_ptr所管理的指针进行交换。


注意事项:
《1》unique_ptr、shared_ptr不能使用同一个裸指针初始化两个或两个以上的对象,如:
shared_ptr s1(pointer);
shared_ptr s2(pointer);
这样会对pointer释放两次,两个shared_ptr对象对pointer的引用都是1。
因此对应一系列的shared_ptr用来管理同一个指针时,只有第一个shared_ptr初始化时使用裸指针,其他的shared_ptr只能使用shared_ptr来初始化,否则就会出现这样的内存问题。
《2》不要使用shared_ptr包装this,否则会导致this释放两次,而使用shared_from_this();当然需要使这个类继承enable_shared_from_this
《3》出现循环引用的时候,需要使用weak_ptr来解决问题:
class Node{
public:
    shared_ptr pre;
    shared_ptr next;
};
shared_ptr parent;
shared_ptr son;
parent->next = son;
son->pre = parent;
这个时候如果打印parent.use_count()和son.use_count()会打印出2,这样会造成内存泄漏。
使用weak_ptr来解决问题:
将Node类中的pre和next使用weak_ptr修饰,那么就不会存在内存泄漏了。
《4》多线程使用shared_ptr时,引用计数和析构都不会有问题,因为C++规定对use_count()的更改必须是没有data race(竞争)的。

你可能感兴趣的:(C++)