C++11新特性之十:enable_shared_from_this

2023-05-16

       enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为:

template< class T > class enable_shared_from_this;
       std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。
       若一个类 T 继承 std::enable_shared_from_this<T> ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr<T> 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr<T> 对象,它与 pt 共享 t 的所有权。

一.使用场合

       当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。

1.为何不直接传递this指针

       使用智能指针的初衷就是为了方便资源管理,如果在某些地方使用智能指针,某些地方使用原始指针,很容易破坏智能指针的语义,从而产生各种错误。

2.可以直接传递share_ptr<this>么?

       答案是不能,因为这样会造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。例如:

#include <memory>
#include <iostream>

class Bad
{
public:
	std::shared_ptr<Bad> getptr() {
		return std::shared_ptr<Bad>(this);
	}
	~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};

int main()
{
	// 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
	std::shared_ptr<Bad> bp1(new Bad());
	std::shared_ptr<Bad> bp2 = bp1->getptr();
	// 打印bp1和bp2的引用计数
	std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
	std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
}  // Bad 对象将会被删除两次
输出结果如下:


当然,一个对象被删除两次会导致崩溃。


正确的实现如下:

#include <memory>
#include <iostream>

struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
	std::shared_ptr<Good> getptr() {
		return shared_from_this();
	}
	~Good() { std::cout << "Good::~Good() called" << std::endl; }
};

int main()
{
	// 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
	{
		std::shared_ptr<Good> gp1(new Good());
		std::shared_ptr<Good> gp2 = gp1->getptr();
		// 打印gp1和gp2的引用计数
		std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
		std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
	}
	system("pause");
} 
输出结果如下:

二.为何会出现这种使用场合

       因为在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。

具体的应用可以参考:Boost.Asio C++ 网络编程之五:TCP回显服务端/客户端

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11新特性之十:enable_shared_from_this 的相关文章

  • 在具有多个模块(如 JHipster)的项目中嵌套角度组件

    我试图在另一个实体组件中显示一个实体组件 我在网上找到了一些关于共享模块的信息 我也检查了这个post https stackoverflow com questions 42284351 jhipster 4 how to put ent
  • 使用共享静态 WCF 代理客户端有哪些陷阱?

    我正在考虑将共享 读取静态 WCF 代理客户端用于高吞吐量应用程序 我相信这样做可以提高性能 但我还没有对此进行基准测试 这个想法有一些严重的缺陷吗 从我的研究中 我可以看到存在处理故障状态的问题 目前尚不清楚该状态对其他待处理请求的影响流
  • 在 JS 中具有正确的“this”值

    我有两个类似的 Javascript 对象 var Object2 new function this FetchData function callback do some stuff callback data var Object1
  • “this”关键字似乎不起作用

    我试图理解如何this关键字在 JavaScript 中有效 我制作了这个脚本 function click this innerHTML changed 在此 HTML 中使用
  • C++ 中“this”指针的用途是什么? [复制]

    这个问题在这里已经有答案了 目的是什么this关键词 类中的方法不能访问同一类中的其他对等成员吗 什么情况需要打电话this在类中调用对等方法 两个主要用途 To pass this or this作为其他非类方法的参数 void do s
  • 'this' 关键字作为属性

    我很了解 C 但这对我来说很奇怪 在一些旧程序中 我看到过这样的代码 public MyType this string name some code that finally return instance of MyType 怎么称呼
  • 使用 Libtool 将静态库强制链接到共享库

    我有一个图书馆 libfoo 编译后的使用libtool分成两个对象 libfoo a 和 libfoo so 我必须创造 使用libtool另外 另一个图书馆 libbar 这将是一个包含所有 libfoo 代码的共享库 libbar s
  • 访问与局部变量(或参数)同名的成员字段

    考虑以下代码片段 struct S S const int a this gt a a option 1 S a a option 2 int a 选项 1 与选项 2 等效吗 是否存在一种形式优于另一种形式的情况 标准的哪个条款描述了这些
  • 对象中对象中的 JavaScript `this`?

    抱歉 帖子标题模糊 我无法为这篇文章制定正确的英文名称 例如我有这样一个对象 var APP a 1 b function return this a 这样 如果我打电话console log APP b than this将引用 APP
  • JS 对象 this.method() 通过 jQuery 中断

    我确信这个问题有一个简单的答案 但现在是星期五下午 我很累 不确定如何解释它 所以我将继续发布示例代码 这是一个简单的对象 var Bob Stuff init function this Stuff arguments 0 doSomet
  • C++ 使用 .o 链接和使用 .a 文件链接之间存在差异:行为不同,为什么?

    我期望 与 o 文件链接和与从 o 文件存档的 a 文件链接应该没有区别 但事实并非如此 我有2个源文件 每个都声明1个类 1个静态对象 1个函数 以及一个调用其中一个函数的main cpp cat First cpp include
  • 如何在 React 上正确地将 onclick 处理程序绑定到 `this`

    解释为什么这不是重复的 我的代码已经可以工作 我已将其作为评论包含在内 问题是为什么this当我将其包含到单击处理程序函数时 上下文会发生变化 我正在尝试 React 中的计算器项目 目标是将 onclick 处理程序附加到数字按钮 以便数
  • Java中共享内存的任何概念

    AFAIK Java中的内存是基于堆的 内存是动态分配给对象的 并且没有共享内存的概念 如果没有共享内存的概念 那么Java程序之间的通信应该是很耗时的 在 C 中 与其他通信模式相比 通过共享内存进行进程间通信更快 如我错了请纠正我 另外
  • “粗箭头”(=>)何时绑定到“this”实例

    粗箭头可以在不同的设置中使用 但不知何故却不能 始终绑定到我想要的实例 粗箭头绑定3次 声明方法时 在方法内声明函数时 在全局上下文中声明函数时 1 声明方法时 当 Coffeescript 编译器遇到以下语法模式时 在类声明中 class
  • Outlook Mapi 访问共享联系人

    我想通过 Mapi 从 Outlook 导入联系人 第一步使用标准接触是没有问题的 MAPIFolder contactObjects outlookObj Session GetDefaultFolder OlDefaultFolders
  • C++ 进程间通信的最佳方式

    我有两个进程 一个进程将查询另一个进程的数据 在有限的时间内 每秒 10000 个 将会有大量的查询 并且每秒将传输数据 gt 100 mb 数据类型将是整数类型 双精度 整数 我的问题是用什么方式连接这个过程 共享内存 消息队列 lpc
  • 如何使用attachEvent引用调用者对象(“t​​his”)

    使用方法 attachEvent 在 IE 中 如何引用调用者对象 触发事件的元素 this In normal浏览器 使用 addEventListener 变量this指向元素 而在 IE 中它指向window object 我需要它与
  • 在java构造函数中传递“this”

    查看以下代码 public class ClassA private boolean ClassAattr false public ClassA ClassAHandler handler new ClassAHandler this p
  • $this 关键字的含义是什么?

    请解释一下这是为了什么 this and gt 代表 让我们以下面的代码为例 this gt convertNamesToCaptions order formId this 指的是当前对象 手册说 当从对象上下文中调用方法时 伪变量 th
  • JS 类没有常量引用“this”来进行成员访问

    我典型的 JS 类结构如下所示 MyClass function args this myProp1 undefined this myProp2 args 0 more member data this foo function retu

随机推荐