【C++】智能指针

您所在的位置:网站首页 智能指针c++实现 【C++】智能指针

【C++】智能指针

2022-05-28 03:51| 来源: 网络整理| 查看: 265

std::unique_ptr

std::shared_ptr

std::weak_ptr

std::unique_ptr

一个unique_ptr独享它指向的对象。也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁时,指向的对象也随即被销毁。

离开作用域自动释放资源

具有move-only性质,独享资源所有权

可以指向数组

可以自定义deleter

std::unique_ptr的构造函数,接受两个参数:

一个数据指针(这个指针可以指向单一数据,也可以是一个数组指针)

一个析构函数(在unique_ptr脱离作用域时调用)

make_unique

make_unique仅能new出一个数据指针,而无法指定析构函数。所以需要自定义析构函数的时候,不能调用make_unique函数来产生std::unique_ptr。

移动unique_ptr对象

在函数中作为参数

下面的代码将编译出错:

正确使用unique_ptr的方式:

小结

当unique_ptr被销毁时, 其指向的原始指针也自动被销毁。

unique_ptr无法被拷贝, 没有拷贝构造和拷贝赋值函数。 

unique_ptr的所有权可以通过move操作转移,由移动构造和移动赋值函数实现。

unique_ptr默认通过delete实现对象销毁。 也可以在构造时指定unique_ptr的销毁函数。

使用默认的销毁函数时, unique_ptr的大小和原始指针相同。使用自定义销毁器时, unique_ptr会将销毁器的类封装在unique_ptr中, 因此应尽量使用无状态的函数对象(没有捕获的lambda表达式或仿函数)作为销毁器, 此时unique_ptr的大小仍然和原始指针相同。

std::shared_ptr

shared_ptr的大小是固定的2倍原始指针大小, 一个是指向原始指针, 一个指向控制块.

共享资源所有权,对资源引用计数(从shared_ptr拷贝构造和拷贝赋值时会使引用计数+1,移动构造和移动赋值引用计数不变.)

当引用计数为0时,自动释放资源

可以指向数组

可以自定义deleter

一个 shared_ptr 对象的内存开销要比裸指针和无自定义 deleter 的 unique_ptr 对象略大。

shared_ptr 对象需要保存两个指针:

指向共享资源的指针。

引用计数等共享资源的控制信息。(指向控制信息的指针)

shared_ptr 的 的 deleter 是保存在控制信息中,所以,是否有自定义 deleter 不影响 shared_ptr 对象的大小。

make_shared

一般情况下, 更推荐使用make_shared来构造shared_ptr。

优点:

若创建原始指针和从原始指针创建shared_ptr之间抛出异常, 可能会发生内存泄漏;

make_shared将对象的内存和控制块内存同时分配, 并同时释放. 这样可以提高执行效率。

缺点:

无法使用大括号初始化;

无法自定义销毁器;

对象内存和控制块内存同时分配同时释放. 这会导致在shared_ptr的引用计数为0, 但weak_ptr引用计数不为0的情况下. 控制块内存无法释放, 会导致对象的那块内存一直无法释放, 造成内存浪费。

std::weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。

weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。

由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock,此函数检查weak_ptr指向的对象是否存在。如果存在,lock返回一个指向共享对象的shared_ptr,如果不存在,lock将返回一个空指针



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3