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

目录
  • 一、提要
  • 二、智能指针boost::shared_ptr与boost::scoped_ptr
  • 三、智能指针 boost::shared_ptr用法
    • 示例1
    • 示例2
    • 示例3
    • 示例4
    • 示例5

一、提要

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ Boost PointerContainer智能指针详解

    目录 一.提要 二.智能指针Boost.PointerContainer 三.练习 一.提要 在 C++11 中,Boost.PointerContainer是另一个智能指针,一般是用来生成集合数据的,本文阐述这种指针的特点和用法. 二.智能指针Boost.PointerContainer 库 Boost.PointerContainer 提供专门用于管理动态分配对象的容器.例如,在 C++11 中,您可以使用 std::vector<std::unique_ptr<int>> 创

  • C++ boost scoped_ptr智能指针详解

    目录 一.智能指针-唯一所有者 二.接口类分析 一.智能指针-唯一所有者 boost::scoped_ptr 是一个智能指针,它是动态分配对象的唯一所有者. boost::scoped_ptr 无法复制或移动.此智能指针在头文件 boost/scoped_ptr.hpp 中定义. 二.接口类分析 scoped_array 分析 scoped_array 的类部分原始代码如下: template<class T> class scoped_array // noncopyable { priva

  • C++ Boost Thread线程使用示例详解

    目录 一.并行编程 二.生成何管理Threads 练习 一.并行编程 以下库支持并行编程模型. Boost.Thread 允许您创建和管理自己的线程. Boost.Atomic 允许您通过多个线程的原子操作访问整数类型的变量. Boost.Lockfree 提供线程安全的容器. Boost.MPI 起源于超级计算机领域.使用 Boost.MPI,您的程序可以多次启动并在多个进程中执行.您专注于对应该并发执行的实际任务进行编程,而 Boost.MPI 会协调这些过程.使用 Boost.MPI,您无

  • C++ Boost Lockfree超详细讲解使用方法

    目录 一.说明 二.示例和代码 Boost.Lockfree 一.说明 Boost.Lockfree 提供线程安全和无锁容器.可以从多个线程访问此库中的容器,而无需同步访问. 在 1.56.0 版本中,Boost.Lockfree 只提供了两个容器:boost::lockfree::queue 类型的队列和 boost::lockfree::stack 类型的栈.对于队列,可以使用第二个实现:boost::lockfree::spsc_queue.此类针对只有一个线程写入队列和只有一个线程从队列

  • C++ Boost EnableIf函数使用介绍

    目录 一.说明 二.Boost.EnableIf的示例 练习 一.说明 Boost.EnableIf Boost.Enable If 可以禁用重载函数模板或专用类模板.禁用意味着编译器忽略相应的模板.这有助于防止出现模棱两可的情况,即编译器不知道要使用哪个重载函数模板.它还可以更轻松地定义不仅可用于特定类型而且可用于一组类型的模板. 从 C++11 开始,Boost.EnableIf 已经成为标准库的一部分.您可以在不使用 Boost 库的情况下调用本章介绍的函数:只需包含头文件 type_tr

  • C++ Boost Atomic详细讲解

    目录 一.说明 二.示例和代码 一.说明 Boost.Atomic 提供类 boost::atomic,可用于创建原子变量.它们被称为原子变量,因为所有访问都是原子的. Boost.Atomic 用于多线程程序,当在一个线程中访问变量不应被访问相同变量的另一个线程中断时.如果没有 boost::atomic,从多个线程访问共享变量的尝试将需要与锁同步. boost::atomic 取决于支持原子变量访问的目标平台.否则,boost::atomic 使用锁.该库允许您检测目标平台是否支持原子变量访

  • C++ Boost Lambda表达式详解

    目录 lambda表达式格式 说明Boost.Lambda lambda表达式格式 lambda表达式的格式 [捕捉列表](参数列表)mutable->返回值类型{ 语句部分 }; 其中参数列表.返回值类型是可选的,捕捉列表.函数体可以为空. 先来看一个较为简单的lamda表达式 int main(void) { auto add = [](int a, int b)->int {return a + b; }; cout << add(1, 2) << endl; r

  • C++ Boost MPI接口详细讲解

    目录 一.说明 二.开发和运行时环境 三.简单数据交换 一.说明 Boost.MPI 提供了 MPI 标准(消息传递接口)的接口.该标准简化了并发执行任务的程序的开发.您可以使用线程或通过共享内存或网络连接使多个进程相互通信来开发此类程序. MPI 的优点是你不需要关心这些细节.您可以完全专注于并行化您的程序. 缺点是您需要 MPI 运行时环境.如果您控制运行时环境,MPI 只是一个选项.例如,如果你想分发一个可以通过双击启动的程序,你将无法使用 MPI.虽然操作系统开箱即用地支持线程.共享内存

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

    目录 一.提要 二.智能指针boost::shared_ptr与boost::scoped_ptr 三.智能指针 boost::shared_ptr用法 示例1 示例2 示例3 示例4 示例5 一.提要 boost::shared_ptr是另一个智能指针,与 boost::scoped_ptr有很大不同,本文阐述这种区别. 二.智能指针boost::shared_ptr与boost::scoped_ptr 主要区别在于: boost::shared_ptr 不一定是对象的独占所有者. 所有权可以

  • C++ Boost Optional示例超详细讲解

    目录 一.概述 二.Boost.Optional 一.概述 数据结构类似于容器,因为它们可以存储一个或多个元素.但是,它们与容器不同,因为它们不支持容器通常支持的操作.例如,使用本部分介绍的数据结构,不可能在一次迭代中访问所有元素. Boost.Optional 可以很容易地标记可选的返回值.使用 Boost.Optional 创建的对象要么是空的,要么包含单个元素.使用 Boost.Optional,您无需使用空指针或 -1 等特殊值来指示函数可能没有返回值. Boost.Tuple 提供了

  • C++ boost thread库用法详细讲解

    目录 一.说明 二.boost::thread的几个函数 三.构造 一.说明 boost::thread的六种使用方法总结,本文初步介绍线程的函数.构造.执行的详细解释. 二.boost::thread的几个函数 函数 功能 join() 让主进程等待子线程执行完毕后再继续执行 get_id() 获得线程的 id 号 detach() 标线程就成为了守护线程,驻留后台运行 bool joinable() 是否已经启动,为 join() thread::join()是个简单暴力的方法,主线程等待子

  • C++ Boost Variant示例超详细讲解

    目录 一.提要 二.示例 一.提要 Boost.Variant 提供了一个类似于 union 的名为 boost::variant 的类.您可以将不同类型的值存储在 boost::variant 变量中.在任何时候只能存储一个值.分配新值时,旧值将被覆盖.但是,新值的类型可能与旧值不同.唯一的要求是这些类型必须作为模板参数传递给 boost::variant,这样它们才能为 boost::variant 变量所知. boost::variant 支持任何类型.例如,可以将 std::string

  • C++ Boost PropertyTree示例超详细讲解

    目录 一.提要 二.应用示例 练习 一.提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对.树形结构意味着一个树干存在许多分支,其中有许多树枝.文件系统是树结构的一个很好的例子.文件系统有一个带有子目录的根目录,这些子目录本身可以有子目录等等. 二.应用示例 要使用 boost::property_tree::ptree,请包含头文件 boost/property_tree/ptree.hpp.这是一个主头文

  • C++ 中boost::share_ptr智能指针的使用方法

    C++ 中boost::share_ptr智能指针的使用方法 最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论.当然,使用boost智能指针首先要编译boost库,具体方法可以网上查询,在此不再赘述. 智能指针能够使C++的开发简单化,主要是它能够自动管理内存的释放,而且能够做更多的事情,即使用智能指针,则可以再代码中new了之后不用delete,智能指针自己会帮助你管理

  • C++ Boost weak_ptr智能指针超详细讲解

    目录 一.提要 二.特别智能指针(Special Smart Pointers) 一.提要 在 C++11 中,boost::weak_ptr是另一类智能指针,一般是用COM组件生成.调用,本文阐述这种指针的特点和用法. 二.特别智能指针(Special Smart Pointers) 到目前为止介绍的每个智能指针都可以在不同的场景中单独使用.但是,boost::weak_ptr 仅在与 boost::shared_ptr 结合使用时才有意义. boost::weak_ptr 在 boost/w

  • C++ Boost log日志库超详细讲解

    目录 一.说明 二.库Boost.Log 一.说明 应用程序库是指通常专门用于独立应用程序开发而不用于库开发的库. Boost.Log 是一个日志库. Boost.ProgramOptions 是一个用于定义和解析命令行选项的库. Boost.Serialization 允许您序列化对象,例如,将它们保存到文件或从文件加载它们. Boost.Uuid 支持使用 UUID. 具体内容 62. Boost.Log 63. Boost.ProgramOptions 64. Boost.Serializ

  • C++ Boost Exception超详细讲解

    Boost.Exception 库提供了一种新的异常类型 boost::exception,它允许您在抛出异常后将数据添加到异常中.此类型在 boost/exception/exception.hpp 中定义.由于 Boost.Exception 将其类和函数分布在多个头文件中,以下示例访问主头文件 boost/exception/all.hpp 以避免一个接一个地包含头文件. Boost.Exception 支持 C++11 标准的机制,该机制将异常从一个线程传输到另一个线程. boost::

随机推荐