Loading

智能指针初探

智能指针是C++11引入的,比裸指针更为强大的指针。主要作用是用来完成一定程度上的内存资源管理自动化。

unique_ptr

unique_ptr实现专属所有权功能。unique_ptr不允许拷贝,只允许移动,保证了没有其他的指针指向unique_ptr指向的对象。unique_ptr被析构时,其析构函数会主动析构所指向的对象。

默认unique_ptr使用delete析构对象,不过它也支持自定义析构器。添加自定义析构器可能会增加unique_ptr的大小,在默认状态下,unique_ptr和裸指针的性能和大小是一张的。

同时unique_ptr可以支持转换成shared_ptr,所以在不知道用什么智能指针的情况下,直接用unique_ptr就完事了。

可以使用make_unique来创建一个unique_ptr

shared_ptr

shared_ptr实现共享所有权功能,内部维护了一个引用计数,只有当引用计数为0时,该shared_ptr被析构才会调用内部指向对象的析构函数。

shared_ptr的复制,会使得其引用计数+1,对其的析构会使得引用计数-1,而对其进行移动,则不会修改引用计数。
shared_ptr同样默认使用delete进行析构,也支持自定义析构器,但是与unique_ptr不同,对其进行自定义析构器不会改变shared_ptr的大小。

image
shared_ptr本身的尺寸是普通指针的两倍,因为其内部实际上维护了两个指针。第二个指针会指向一个叫做控制块的数据结构,里面维护了许多信息。

  • shared_ptr第一次被make出来时,它会创建一个控制块。
  • shared_ptrunique_ptr转化过来时,也会创建一个控制块。
  • shared_ptr从一个裸指针转化过来时,也会创建一个控制块。

其中,从裸指针转换成shared_ptr是最危险的,因为你可以转换任意多次,这会导致拥有对同一个对象的若干个控制块,而每一个控制块的引用计数归0时都会引发一次析构,也就是会导致多重析构的结构。所以实践中尽量避免。

weak_ptr

weak_ptr属于是shared_ptr的补丁。这么说是因为,shared_ptr有一个无法绕过的槛,循环引用。假设你有两个shared_ptr,分别是A和B。令A指向B,令B指向A,那么此时双方的引用计数永远都是1,也就是永远都不会析构,已经达成了事实上的内存泄漏。

但是这种相互引用的需求本身是真实存在的,就比如说图数据结构,一个节点可以被其他节点引用,同样也会引用很多其他的节点。所以在这种情况下,shared_ptr行不通,那就要使用weak_ptr
weak_ptr不会影响shared_ptr的引用计数,可以从shared_ptr中创建一个weak_ptr出来。而weak_ptr就具有检测这个shared_ptr是否为空的功能,并且可以根据需要,返回这个shared_ptr,使得你可以访问weak_ptr所指向的对象。

posted @ 2023-07-20 18:55  烤肉kr  阅读(8)  评论(0编辑  收藏  举报