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

时间: 2022-11-17

C++&nbsp;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++&nbsp;Boost&nbsp;PointerContainer智能指针详解

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

C++&nbsp;boost&nbsp;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++&nbsp;Boost&nbsp;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++&nbsp;Boost&nbsp;Optional示例超详细讲解

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

C++&nbsp;Boost&nbsp;Variant示例超详细讲解

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

C++&nbsp;Boost&nbsp;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的智能指针shared_ptr

boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以共享所有权的智能指针,首先让我们通过一个例子看看它的基本用法: #include <string> #include <iostream> #include <boost/shared_ptr.hpp> class implementation { public: ~imp

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语言详细讲解多维数组与多维指针

目录 一.指向指针的指针 二.二维数组与二维指针 三.数组名 四.小结 一.指向指针的指针 指针的本质是变量 指针会占用一定的内存空间 可以定义指针的指针来保存指针变量的地址值 为什么需要指向指针的指针? 指针在本质上也是变量 对于指针也同样存在传值调用与传址调用 下面看一个重置动态空间大小(从 size 到 new_size)的代码: #include <stdio.h> #include <malloc.h> int reset(char** p, int size, int

C语言&nbsp;详细讲解数组参数与指针参数

目录 一.C语言中的数组参数退化为指针的意义 二.二维数组参数 三.等价关系 四.被忽视的知识点 五.小结 一.C语言中的数组参数退化为指针的意义 C 语言中只会以值拷贝的方式传递参数 当向函数传递数组时: 将整个数组拷贝一份传入函数        × 将数组名看做常量指针传数组首元素地址    √ C 语言以高效作为最初设计目标: a) 参数传递的时候如果拷贝整个数组执行效率将大大下降. b) 参数位于栈上,太大的数组拷贝将导致栈溢出. 二.二维数组参数 二维数组参数同样存在退化的问题 二维数

C语言超详细讲解指针的概念与使用

目录 一.指针与一维数组 1. 指针与数组基础 2. 指针与数组 3. 一个思考 二.指针与字符串 三.指针和二维数组 1. 指针数组与数组指针 2. 指针数组 3. 数组指针 一.指针与一维数组 1. 指针与数组基础 先说明几点干货: 1. 数组是变量的集合,并且数组中的多个变量在内存空间上是连续存储的. 2. 数组名是数组的入口地址,同时也是首元素的地址,数组名是一个地址常量,不能更改. 3. 数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的其实地址. 对于第一点数