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/weak_ptr.hpp 中定义。

示例1.Usingboost::weak_ptr

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <thread>
#include <functional>
#include <iostream>
void reset(boost::shared_ptr<int> &sh)
{
  sh.reset();
}
void print(boost::weak_ptr<int> &w)
{
  boost::shared_ptr<int> sh = w.lock();
  if (sh)
    std::cout << *sh << '\n';
}
int main()
{
  boost::shared_ptr<int> sh{new int{99}};
  boost::weak_ptr<int> w{sh};
  std::thread t1{reset, std::ref(sh)};
  std::thread t2{print, std::ref(w)};
  t1.join();
  t2.join();
}

boost::weak_ptr 必须使用 boost::shared_ptr 进行初始化。它最重要的成员函数是 lock()。 lock() 返回一个 boost::shared_ptr ,它与用于初始化弱指针的共享指针共享所有权。如果共享指针为空,则返回的指针也将为空。

boost::weak_ptr 是有意义的,只要一个函数需要与一个由共享指针管理的对象一起工作,但对象的生命周期不依赖于函数本身。该函数只能使用该对象,只要它由程序中其他位置的至少一个共享指针拥有。如果共享指针被重置,则对象无法保持活动状态,因为相应函数内有一个额外的共享指针。

示例 1 在 main() 中创建了两个线程。第一个线程执行函数 reset(),该函数接收对共享指针的引用。第二个线程执行函数 print(),该函数接收对弱指针的引用。这个弱指针之前已经用共享指针初始化了。

程序启动后,reset() 和 print() 会同时执行。但是,无法预测执行顺序。这会导致当对象被 print() 访问时,reset() 会破坏该对象的潜在问题。

弱指针通过以下方式解决了这个问题:调用 lock() 返回一个共享指针,该指针指向一个有效对象(如果在调用时存在一个有效对象)。如果不是,则共享指针设置为 0,相当于一个空指针。

boost::weak_ptr 本身对对象的生命周期没有任何影响。为了安全地访问 print() 函数中的对象,lock() 返回一个 boost::shared_ptr。这保证了即使不同的线程尝试释放对象,由于返回的共享指针,它仍将继续存在。

示例2 .使用boost::intrusive_ptr

#include <boost/intrusive_ptr.hpp>
#include <atlbase.h>
#include <iostream>
void intrusive_ptr_add_ref(IDispatch *p) { p->AddRef(); }
void intrusive_ptr_release(IDispatch *p) { p->Release(); }
void check_windows_folder()
{
  CLSID clsid;
  CLSIDFromProgID(CComBSTR{"Scripting.FileSystemObject"}, &clsid);
  void *p;
  CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, __uuidof(IDispatch), &p);
  boost::intrusive_ptr<IDispatch> disp{static_cast<IDispatch*>(p), false};
  CComDispatchDriver dd{disp.get()};
  CComVariant arg{"C:\\Windows"};
  CComVariant ret{false};
  dd.Invoke1(CComBSTR{"FolderExists"}, &arg, &ret);
  std::cout << std::boolalpha << (ret.boolVal != 0) << '\n';
}
int main()
{
  CoInitialize(0);
  check_windows_folder();
  CoUninitialize();
}

通常,boost::intrusive_ptr 的工作方式与 boost::shared_ptr 相同。但是,虽然 boost::shared_ptr 会跟踪引用特定对象的共享指针的数量,但开发人员在使用 boost::intrusive_ptr 时必须这样做。如果其他类已经跟踪引用,这可能是有意义的。

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

示例 2 使用 COM 提供的功能,因此只能在 Windows 上构建和运行。 COM 对象是 boost::intrusive_ptr 的一个很好的例子,因为它们跟踪引用它们的指针的数量。内部引用计数器可以通过成员函数 AddRef() 和 Release() 递增或递减 1。一旦计数器达到 0,COM 对象就会自动销毁。

​​​ 从 intrusive_ptr_add_ref() 和 intrusive_ptr_release() 调用两个成员函数 AddRef() 和 Release()。 Boost.Intrusive 希望开发人员定义这两个函数,当引用计数器必须递增或递减时,它们会自动调用。传递给这些函数的参数是指向用于实例化类模板 boost::intrusive_ptr 的类型的指针。

此示例中使用的 COM 对象称为 FileSystemObject,默认情况下可在 Windows 上使用。它提供对底层文件系统的访问,例如,检查给定目录是否存在。在示例 1.9 中,检查了名为 C:\Windows 的目录是否存在。其内部工作方式仅取决于 COM,与 boost::intrusive_ptr 的功能无关。关键是一旦侵入指针 disp 在 check_windows_folder() 结束时超出范围,函数 intrusive_ptr_release() 就会被自动调用。这反过来会将 FileSystemObject 的内部引用计数器减为 0 并销毁该对象。

传递给 boost::intrusive_ptr 的构造函数的参数 false 会阻止 intrusive_ptr_add_ref() 被调用。当使用 CoCreateInstance() 创建 COM 对象时,计数器已设置为 1。因此,不得使用 intrusive_ptr_add_ref() 递增。

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

(0)

相关推荐

  • 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 ScopeExit超详细讲解

    目录 一.提要 二.退出作用域(Boost.ScopeExit) 2.1 范例1.UsingBOOST_SCOPE_EXIT 2.2 示例2.Boost.ScopeExit和C++11的lambda函数 2.3 示例3.特点BOOST_SCOPE_EXIT 三.练习 一.提要 资源有很多种,每种都封装一套,还是挺繁琐的!对于比较少使用或者一个程序很可能只会用一次的资源,我们不想封装,在这种情况下用Boost.ScopeExit. 二.退出作用域(Boost.ScopeExit) 库 Boost.

  • C++ Boost StringAlgorithms超详细讲解

    目录 一.提要 二.简化字符串处理的工具和其库 三.应用Boost.StringAlgrithms库 3.1 字符大小写 3.2 删除字符串内子串 3.3 查找字符串内子串 3.4 合并字符串 3.5 子串替换 3.6 字符串修剪 3.7 创立谓词 3.8 比较 3.9 拆分字符串 3.10 查找字符串 练习 一.提要 boost C++对应的字符串对象也有一套标准操作方法.本文介绍库Boost.StringAlgorithms的若干函数和功能示例. 二.简化字符串处理的工具和其库 Boost.

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

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

    目录 一.引言 二.Boost.LexicalCast 2.1 示例1 2.2 示例2 三.lexical_cast与c/c++提供类似接口的比较 3.1 两者比较 3.2 样例 一.引言 在boost库中,有一个函数Boost.LexicalCast可以将数字和字符串进行双向转换.本文介绍这种用法的案例. 二.Boost.LexicalCast Boost.LexicalCast 提供了一个转换运算符,boost::lexical_cast,它可以将数字从字符串转换为数字类型,例如 int 或

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

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

  • 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 MetaStateMachine定义状态机超详细讲解

    目录 一.说明 二.示例和代码 一.说明 Boost.MetaStateMachine 用于定义状态机.状态机通过对象的状态来描述对象.它们描述了存在哪些状态以及状态之间可能存在哪些转换. Boost.MetaStateMachine 提供了三种不同的方式来定义状态机.创建状态机所需编写的代码取决于前端. 如果使用基本前端或函数前端,则可以用常规方式定义状态机:创建类,从 Boost.MetaStateMachine 提供的其他类派生它们,定义所需的成员变量,并编写所需的 C++自己编码.基本前

  • C语言指针超详细讲解上篇

    目录 前言 1.指针是什么 1.1 指针变量 1.2 指针是内存中一个最小单元的编号 2.指针和指针类型 2.1 指针±类型 2.2 指针的解引用 2.2.1 int* 类型的解引用 2.2.2 char* 类型的解引用 3.野指针 3.1 野指针成因 3.1.1 指针未初始化 3.1.2 指针越界访问 3.1.3 指针指向的空间释放 3.2 如何规避野指针 总结 前言 本文开始指针相关内容的学习,主要内容包括: 指针是什么 指针和指针类型 野指针 指针运算 指针和数组 二级指针 指针数组 1.

  • C语言指针超详细讲解下篇

    目录 前言 指针运算 指针±整数 4.1 指针±整数 4.2 指针-指针 4.3 指针的关系运算 5.指针和数组 6.二级指针 7.指针数组 7.1 举例 1 7.2 举例 2 总结 前言 本文接着上一篇内容,继续学习指针相关知识点. 指针运算 指针±整数 指针-指针 指针的关系运算 4.1 指针±整数 #define VALUE 5 int main() { float values[VALUE]; float *vp; //指针+-指针,关系运算 for (vp = &values[0];

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

    目录 一.内存泄漏-永恒的话题 二.深度思考 三.智能指针分析 四.小结 一.内存泄漏-永恒的话题 动态申请堆空间,用完后不归还 C++ 语言中没有垃圾回收的机制 指针无法控制所指堆空间的生命周期 下面看一段内存泄漏的代码: #include <iostream> #include <string> using namespace std; class Test { int i; public: Test(int i) { this->i = i; } int value()

  • C++ Boost Exception超详细讲解

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

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

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

  • C++ Boost ProgramOptions超详细讲解

    目录 一.说明 二.示例Boost.ProgramOptions 一.说明 Boost.ProgramOptions Boost.ProgramOptions 是一个可以轻松解析命令行选项的库,例如,控制台应用程序.如果您使用图形用户界面开发应用程序,命令行选项通常并不重要. 要使用 Boost.ProgramOptions 解析命令行选项,需要以下三个步骤: 定义命令行选项.您给它们命名并指定哪些可以设置为一个值.如果命令行选项被解析为键/值对,您还可以设置值的类型——例如,它是字符串还是数字

随机推荐