C++ Boost shared_ptr共享指针详细讲解

 更新时间:2022年11月17日 16:38:19   作者:无水先生  
shared_ptr是一个标准的共享所有权的智能指针,允许多个指针指向同一个对象,定义在memory文件中,命名空间为std,这篇文章主要介绍了C++ shared_ptr使用,需要的朋友可以参考下

一、提要

boost::shared_ptr是另一个智能指针,与 boost::scoped_ptr有很大不同,本文阐述这种区别。

二、智能指针boost::shared_ptr与boost::scoped_ptr

主要区别在于:

  • boost::shared_ptr 不一定是对象的独占所有者。
  • 所有权可以与 boost::shared_ptr 类型的其他智能指针共享。在这种情况下,共享对象不会被释放,直到引用该对象的共享指针的最后一个副本被销毁。
  • 因为 boost::shared_ptr 可以共享所有权,所以可以复制智能指针,而这对于 boost::scoped_ptr 是不可能的。

boost::shared_ptr定义在boost/shared_ptr.hpp.

三、智能指针 boost::shared_ptr用法

示例1

基本调用boost::shared_ptr

示例 1

#include <boost/shared_ptr.hpp>
#include <iostream>
int main()
{
  boost::shared_ptr<int> p1{new int{1}};
  std::cout << *p1 << '\n';
  boost::shared_ptr<int> p2{p1};
  p1.reset(new int{2});
  std::cout << *p1.get() << '\n';
  p1.reset();
  std::cout << std::boolalpha << static_cast<bool>(p2) << '\n';
}

示例 1 使用了 boost::shared_ptr 类型的两个智能指针 p1 和 p2。 p2 用 p1 初始化,这意味着两个智能指针共享同一个 int 对象的所有权。当在 p1 上调用 reset() 时,一个新的 int 对象被锚定在 p1 中。这并不意味着现有的 int 对象被销毁。由于它也锚定在 p2 中,因此它继续存在。在调用 reset() 之后,p1 是编号为 2 的 int 对象的唯一所有者,而 p2 是编号为 1 的 int 对象的唯一所有者。

boost::shared_ptr 在内部使用引用计数器。只有当 boost::shared_ptr 检测到智能指针的最后一个副本已被销毁时,才会使用 delete 释放包含的对象。

与 boost::scoped_ptr 一样,boost::shared_ptr 重载 operator bool()、operator*() 和 operator->()。成员函数 get() 和 reset() 用于检索当前存储的地址或存储新地址。

作为第二个参数,可以将删除器传递给 boost::shared_ptr 的构造函数。删除器必须是一个函数或函数对象,它接受实例化时使用的 boost::shared_ptr 类型的指针作为其唯一参数。在析构函数中调用删除器而不是删除。这使得管理 boost::shared_ptr 中动态分配的对象以外的资源成为可能。

示例2

boost::shared_ptr用户自定义删除

示例 2

#include <boost/shared_ptr.hpp>
#include <Windows.h>
int main()
{
  boost::shared_ptr<void> handle(OpenProcess(PROCESS_SET_INFORMATION, FALSE,
    GetCurrentProcessId()), CloseHandle);
}

在示例2 boost::shared_ptr 被实例化为 void。传递给构造函数的第一个参数是 OpenProcess() 的返回值。 OpenProcess() 是一个用于获取进程句柄的 Windows 函数。在示例中,OpenProcess() 返回当前进程的句柄 - 示例本身。

Windows 使用句柄来引用资源。一旦不再使用资源,必须使用 CloseHandle() 关闭句柄。 CloseHandle() 期望的唯一参数是要关闭的句柄。在示例中,CloseHandle() 作为第二个参数传递给 boost::shared_ptr 的构造函数。 CloseHandle() 是句柄的删除器。当在 main() 结束时销毁句柄时,析构函数调用 CloseHandle() 以关闭作为第一个参数传递给构造函数的句柄。

示例2 之所以有效,是因为 Windows 句柄被定义为 void*。如果 OpenProcess() 没有返回 void* 类型的值,并且如果 CloseHandle() 没有预期 void* 类型的参数,则无法在此示例中使用 boost::shared_ptr。删除器不会使 boost::shared_ptr 成为管理任意资源的灵丹妙药。

示例3

boost::make_shared

#include <boost/make_shared.hpp>
#include <typeinfo>
#include <iostream>
int main()
{
  auto p1 = boost::make_shared<int>(1);
  std::cout << typeid(p1).name() << '\n';
  auto p2 = boost::make_shared<int[]>(10);
  std::cout << typeid(p2).name() << '\n';
}

Boost.SmartPointers 在 boost/make_shared.hpp 中提供了一个辅助函数 boost::make_shared()。使用 boost::make_shared(),您可以创建 boost::shared_ptr 类型的智能指针,而无需自己调用 boost::shared_ptr 的构造函数。

boost::make_shared() 的优点是必须动态分配的对象内存和智能指针内部使用的引用计数器的内存可以保留在一个块中。使用 boost::make_shared() 比调用 new 来创建动态分配的对象并在 boost::shared_ptr 的构造函数中再次调用 new 来为引用计数器分配内存更有效。

您也可以对数组使用 boost::make_shared()。在示例 1.5 中第二次调用 boost::make_shared() 时,一个具有十个元素的 int 数组被锚定在 p2 中。

boost::shared_ptr 自 Boost 1.53.0 起仅支持数组。 boost::shared_array 提供了一个类似于 boost::shared_ptr 的智能指针,就像 boost::scoped_array 类似于 boost::scoped_ptr 一样。当使用 Visual C++ 2013 和 Boost 1.53.0 或更高版本构建时,示例 1.5 为 p2 打印 class boost::shared_ptr<int [0]>。

从 Boost 1.53.0 开始,boost::shared_ptr 支持单个对象和数组,并检测是否必须使用 delete 或 delete[] 释放资源。因为 boost::shared_ptr 还重载了 operator[](自 Boost 1.53.0 起),所以这个智能指针是 boost::shared_array 的替代方案。

示例4

boost::shared_array

Example 4 .Using

#include <boost/shared_array.hpp>
#include <iostream>
int main()
{
  boost::shared_array<int> p1{new int[1]};
  {
    boost::shared_array<int> p2{p1};
    p2[0] = 1;
  }
  std::cout << p1[0] << '\n';
}

boost::shared_array 补充 boost::shared_ptr:由于 boost::shared_array 在析构函数中调用 delete[],所以这个智能指针可以用于数组。对于早于 Boost 1.53.0 的版本,boost::shared_array 必须用于数组,因为 boost::shared_ptr 不支持数组。

boost::shared_array 在 boost/shared_array.hpp 中定义。

在示例4 中,智能指针 p1 和 p2 共享动态分配的 int 数组的所有权。当使用 operator[] 访问 p2 中的数组以存储数字 1 时,使用 p1 访问相同的数组。因此,该示例将 1 写入标准输出。

与 boost::shared_ptr 一样,boost::shared_array 使用引用计数器。当 p2 被销毁时,动态分配的数组不会被释放,因为 p1 仍然包含对该数组的引用。只有当 p1 的作用域结束时,该数组才会在 main() 结束时被销毁。

boost::shared_array 还提供了成员函数 get() 和 reset()。此外,它使运算符 operator bool 过载。

示例5

boost::shared_ptrBOOST_SP_USE_QUICK_ALLOCATOR

Example5.boost::shared_ptrBOOST_SP_USE_QUICK_ALLOCATOR

#define BOOST_SP_USE_QUICK_ALLOCATOR
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ctime>
int main()
{
  boost::shared_ptr<int> p;
  std::time_t then = std::time(nullptr);
  for (int i = 0; i < 1000000; ++i)
    p.reset(new int{i});
  std::time_t now = std::time(nullptr);
  std::cout << now - then << '\n';
}

选择像 boost::shared_ptr 这样的智能指针而不是标准库中的智能指针是有意义的。 Boost.SmartPointers 支持宏来优化智能指针的行为。示例 5 使用宏 BOOST_SP_USE_QUICK_ALLOCATOR 来激活 Boost.SmartPointers 附带的分配器。此分配器管理内存块以减少对引用计数器的 new 和 delete 调用次数。该示例调用 std::time() 来测量循环前后的时间。虽然执行循环所需的时间取决于计算机,但使用BOOST_SP_USE_QUICK_ALLOCATOR 的示例可能会比不使用时运行得更快。 Boost.SmartPointers 的文档没有提到 BOOST_SP_USE_QUICK_ALLOCATOR。因此,您应该分析您的程序并比较使用和不使用 BOOST_SP_USE_QUICK_ALLOCATOR 获得的结果。

Chapter1.Boost.SmartPointers - Shared Ownership (theboostcpplibraries.com)

到此这篇关于C++ Boost shared_ptr共享指针详细讲解的文章就介绍到这了,更多相关C++ Boost shared_ptr内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Qt编写地图迁徙图的实现示例

    Qt编写地图迁徙图的实现示例

    本文主要介绍了Qt编写地图迁徙图的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • C++ 虚函数专题

    C++ 虚函数专题

    这篇文章主要介绍了C++中虚函数的知识点,文中配合代码讲解非常细致,供大家参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 深入剖析OpenMP锁的原理与实现

    深入剖析OpenMP锁的原理与实现

    在本篇文章当中主要给大家介绍一下 OpenMP 当中经常使用到的锁并且仔细分析它其中的内部原理!文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2023-01-01
  • 使用OpenGL创建窗口的示例详解

    使用OpenGL创建窗口的示例详解

    OpenGL,也就是Open Graphics Library。其主要就是用于我们去渲染2D、3D矢量图形的一种跨语言、跨平台的应用程序编程接口,这篇文章主要介绍了使用OpenGL创建窗口,需要的朋友可以参考下
    2022-04-04
  • 详解C++编程中的嵌套类的声明与其中的函数使用

    详解C++编程中的嵌套类的声明与其中的函数使用

    这篇文章主要介绍了C++编程中的嵌套类的声明与其中的函数使用,嵌套类即在一个类的范围内声明和编写另一个类,需要的朋友可以参考下
    2016-01-01
  • C++  数据结构链表的实现代码

    C++ 数据结构链表的实现代码

    这篇文章主要介绍了C++ 数据结构链表的实现代码的相关资料,需要的朋友可以参考下
    2017-01-01
  • C++深入浅出探索数据结构的原理

    C++深入浅出探索数据结构的原理

    C++的数据结构很多,很复杂,所以本文将通过示例带大家深入了解一下C++中的数据结构与算法。文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-05-05
  • C++之构造函数默认值设置方式

    C++之构造函数默认值设置方式

    这篇文章主要介绍了C++之构造函数默认值设置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • C++数据结构与算法之双缓存队列实现方法详解

    C++数据结构与算法之双缓存队列实现方法详解

    这篇文章主要介绍了C++数据结构与算法之双缓存队列实现方法,结合实例形式分析了双缓存队列的原理、实现方法与相关注意事项,需要的朋友可以参考下
    2017-08-08
  • C++11 nullptr实现初始化空指针

    C++11 nullptr实现初始化空指针

    避免产生“野指针”最有效的方法,就是在定义指针的同时完成初始化操作,本文主要介绍了C++11 nullptr初始化空指针,感兴趣的可以了解一下
    2022-01-01

最新评论