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

 更新时间:2022年11月17日 11:03:38   作者:无水先生  
智能指针是一种像指针的C++对象,但它能够在对象不使用的时候自己销毁掉。虽然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷贝和赋值操作),因此很少有人使用。它是Boost各组件中,应用最为广泛的一个

一、提要

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

相关文章

  • C++实现LeetCode165.版本比较)

    C++实现LeetCode165.版本比较)

    这篇文章主要介绍了C++实现LeetCode165.版本比较),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • c语言实现两个值互相交换的函数

    c语言实现两个值互相交换的函数

    本文通过代码给大家介绍c语言实现两个值互相交换的函数,通过实例代码给大家讲解的很详细,具有一定的参考借鉴价值,对c语言两个值互换函数相关知识感兴趣的朋友一起看看吧
    2021-05-05
  • Qt读写XML文件的方法详解(含源码+注释)

    Qt读写XML文件的方法详解(含源码+注释)

    XML文件可以用来存储项目中的数据,它相当于一个简单的数据库,下面这篇文章主要给大家介绍了关于Qt读写XML文件(含源码+注释)的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • 一篇文章彻底搞懂C++常见容器

    一篇文章彻底搞懂C++常见容器

    容器就是一些特定类型对象的集合,容器可以分为顺序容器和关联容器,下面这篇文章主要给大家介绍了关于C++常见容器的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • C语言中条件判断的正确使用姿势

    C语言中条件判断的正确使用姿势

    在C语言中,有三种条件判断结构:if语句、if-else语句和switch语句,这篇文章主要来和大家讲解一下它们的正确使用姿势,需要的可以参考一下
    2023-05-05
  • C++实现学生信息管理系统(Map实现)

    C++实现学生信息管理系统(Map实现)

    这篇文章主要为大家详细介绍了C++实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言中如何实现桶排序

    C语言中如何实现桶排序

    这篇文章主要介绍了C语言中如何实现桶排序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 一文学会数据结构-堆

    一文学会数据结构-堆

    本文主要介绍了数据结构-堆,文中通过图片和大量的代码讲解的非常详细,需要学习的朋友可以参考下这篇文章,希望可以帮助到你
    2021-08-08
  • C/C++中组合详解及其作用介绍

    C/C++中组合详解及其作用介绍

    这篇文章主要介绍了C/C++中组合的详解及其作用介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • QT进行CSV文件初始化与读写操作

    QT进行CSV文件初始化与读写操作

    这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助
    2025-04-04

最新评论