由于其限制(独家所有权),唯一的_ptr通常用于多线程操作。当在多线程中运行时,您可以共享资源并自动发布资源,该资源介绍了Shared_ptr。
为了支持跨线程访问,shared_ptr,其中有一个参考计数(线程安全),以记录当前使用资源的共享_ptr的数量。在使用结束时,参考计数为-1。当参考计数为0时,它将美丽地释放其相关资源。
与unique_ptr的独家所有权相比,shared_ptr可以共享所有权。内部有一个参考计数,用于记录共享资源的共享_ptr的数量。当共享数为0时,它将自动发布其关联资源。
与solution_ptr相比,shared_ptr不支持数组,因此,如果使用shared_ptr指向数组,则需要手动实现exter,如下所示:
shared_ptr多个指针指向同一对象。shared_ptr使用参考计数,每个共享_ptr副本coppy coppy op to同一内存。对于每个人,内部参考计数加1,每个破坏,内部参考计数在1时降低1,当减小降低到0,自动删除尖的堆栈内存。共享_ptr内部的参考计数是线程-SAFE,但是需要锁定对象的读数。
所有智能指针类都有一个明确的构造函数,它使用指针作为参数。因此,无需将指针转换为智能指针:
让我们看一个简单的例子:
从上面可以看出,参考数量将增加计数。我们可以使用use_count方法打印特定的计数。
有三种方法可以将值分配给共享_ptr,如下所示
查看下面的make_shared的使用:
效率提高std :: make_shared(而不是直接使用新的)是一项功能,它可以提高效率。使用std :: make_shared允许编译器生成较小且更快的代码,并且生成的代码使用更简单的数据结构。考虑介绍直接遵循代码:
显然,此代码需要分配,但实际上分配了两次。EHTstd :: shared_ptr指向控制块,并且控制块包含一个参考计数和其他指向对象的内容。此控制块的内存为在std :: shared_ptr.的构造函数中分配了,直接使用了新的使用,需要内存才能分配到小部件,并且还将内存分配给控件块。如果您使用std :: make_shared替换:
一次分配就足够了。这是因为std :: make_shared适用一个单独的内存块来存储窗口小部件对象和控制块。此优化减少了程序的静态大小,因为代码仅包含该程序记忆的呼叫分布,这将加快代码的执行加快,因为内存仅分配一次。此外,使用std :: make_shared消除了控制块需要记录的一些信息,因此程序可能会减少。
STD :: make_shared的效率分析可以应用于std :: allocate_shared,因此std :: make_shared的性能优势也可以扩展到此功能。
异常安全
另一个std :: make_shared的优点是它非常安全。让我们看以下简单代码:
简而言之,上述代码可能发生在内存泄漏中。让我们首先查看以下电话中几个句子的执行顺序。订单可能如下:
如果按照上述代码的顺序执行,则在运行时期,如果在第二版()中生成异常,则该程序将直接返回,新测试分配分配的内存将被泄露,因为它永远不会泄露永远无法在第三步中存储toit,以管理其std :: shared_ptr.,但如果您使用std :: make_shared,则可以避免此问题。呼叫代码看起来像这样:
在运行时,无论哪个在std :: make_shared或secondfun之前被调用。如果std :: make_shared首先称为secondfun调用,则可以将动态分配的测试的原始指针安全存储在std ::::::::::shared_ptr.如果是在第二次fun之后生成异常,则std :: shared_ptr的驱动器会发现它所保留的测试需要被销毁。并且首先调用了第二个fun并生成例外,则不会称呼STD :: make_shard,因此不会被调用,所以这里无需考虑这里的动态分配测试。
我们总是说共享_ptr中的计数是线程-Safe。实际上,shared_ptr中的计数使用了我们上一篇文章引入的std ::原子功能。参考计数加上一个减少是原子,因此线程是安全的。参考计数器的使用价格:std :: memory_order_relaxed的std :: atomic :: fetch_add增加(自我减少顺序需要更强大的顺序,需要更强大的订单,破坏控制控制权带有安全性)。
输出:
在某些情况下,我们将遇到一种情况,即如何安全地获取目标指针,通常,我们不建议直接返回该指针。可以想象存在这种情况。当对象被破坏时,本地或全局变量,但是外部变量并不知道指向指向指向的对象已经破坏。如果此指针目前继续使用此指针,则该程序将崩溃。自然要考虑一下指针操作的对象,并且很自然地认为智能指针非常合适!让我们看看以下内容程序:
编译运行后的程序输出如下:
从上方的输出可以看出构造函数一次被称为一次,但驱动器被称为两次。显然,这是不正确的,这是解决这个问题的。
std :: enable_shared_from__this允许对象(假设其名称t,并且已由std :: shared_ptr对象管理)来生成其他附加的std :: shared_ptr实例(假设名称pt1,pt2,...)他们共享了他们的所有权具有PT的对象t(这是密钥,直接使用它来实现此效果)。
函数将返回一个新对象,该对象与PT共享T。因此,以下代码中显示了使用方法:
通过类中的定义函数构造对象,并可以与其他共享_ptr.generally共享测试对象,我们在异步线程中使用。在异步调用中,有一种保存机制。我们不能由执行异步函数的时间点确定。为了确保变量在异步函数期间有效,我们可以将共享_ptr传递到异步函数到异步函数,以便对象在执行异步函数期间由share_ptr管理不会破坏,并且所使用的变量将始终有效。(键)。
智能指针是模板类,而不是指针。当创建一个智能指针时,必须针对指针的类型,等等。智能指针基本上是在加载操作符号类。该课程用于实现内存的管理,以确保即使存在异常,它也可以通过智能指针类的损坏来完成内存的释放。特别是,它使用参考计数技术和C ++ RAII(资源获取是初始化)特征。
原始:https://juejin.cn/post/7102684262737903653