- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
std::enable_shared_from_this<T>
的类能够在其自身实例中通过 std::shared_from_this
方法创建一个指向自己的 std::shared_ptr<T>
智能指针。std::shared_ptr<T>
实例会造成严重的后果,其行为是未定义的。std::enable_shared_from_this<T>
实际包含了一个用于指向对象自身的 std::weak_ptr<T>
指针。本文介绍 std::enable_shared_from_this 及 std::shared_from_this 的基本概念和使用方法.
以下内容是 cppreference.com 上关于 std::enable_shared_from_this 的定义和说明:
Defined in header < memory > template< class T > class enable_shared_from_this; (since C++11) 。
std::enable_shared_from_this allows an object t that is currently managed by a std::shared_ptr named pt to safely generate additional std::shared_ptr instances pt1, pt2, ... that all share ownership of t with pt. 。
Publicly inheriting from std::enable_shared_from_this<T> provides the type T with a member function shared_from_this. If an object t of type T is managed by a std::shared_ptr<T> named pt, then calling T::shared_from_this will return a new std::shared_ptr<T> that shares ownership of t with pt. 。
简单来说就是,继承自 std::enable_shared_from_this<T> 的类能够在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的 std::shared_ptr<T> 智能指针.
想要理解 std::enable_shared_from_this<T>,首先得知道为什么需要 std::enable_shared_from_this<T>,请看下文.
为什么需要 std::enable_shared_from_this<T>? 我们从一个例子讲起,会更容易一些.
假定有一个类 Processor, 它的作用是异步处理数据并且存储到数据库。当 Processor 接收到数据时,它通过一个定制的 Executor 类型来异步处理数据:
class Executor {
public:
//Executes a task asynchronously
void
execute(const std::function<void(void)>& task);
//....
private:
/* Contains threads and a task queue */
};
class Processor {
public:
//...
//Processes data asynchronously. (implemented later)
void processData(const std::string& data);
private:
//Called in an Executor thread
void doProcessAndSave(const std::string& data) {
//1. Process data
//2. Save data to DB
}
//.. more fields including a DB handle..
Executor* executor;
};
Client 类包含了一个 std::shared_ptr<Processor> 实例,Processor 从 Client 类接收数据:
class Client {
public:
void someMethod() {
//...
processor->processData("Some Data");
//..do something else
}
private:
std::shared_ptr<Processor> processor;
};
以上示例中,Executor 是一个线程池,用于执行任务队列中的任务。 在 Processor::processData 中,我们需要传递一个(指针)函数(lambda 函数)给 Executor 来执行异步操作。该 lambda 函数调用 Processor::doProcessAndSave 以完成实际的数据处理工作。因此,该 lambda 函数需要捕获一个 Processor 对象的引用/指针。我们可以这样做:
void Processor::processData(const std::string& data) {
executor->execute([this, data]() { //<--Bad Idea
//Executes in an Executor thread asynchronously
//'this' could be invalid here.
doProcessAndSave(data);
});
}
然而,因为种种原因,Client 可能会随时重置 std::shared_ptr<Processor>,这可能导致 Processor 的实例被析构。因此,在执行 execute 函数时或者在执行之前,上述代码中捕获的 this 指针随时可能会变为无效指针.
怎么办?
我们可以通过在 lambda 函数中捕获并保留一个指向当前对象本身的 std::shared_ptr<Processor> 实例来防止 Processor 对象被析构.
下图展示了示例代码的交互逻辑:
那么,在 Processor 实例中通过 shared_ptr (this) 创建一个智能指针呢?其行为是未定义的! 。
std::shared_ptr<T> 允许我们安全地访问和管理对象的生命周期。多个 std::shared_ptr<T> 实例通过一个共享控制块结构(a shared control block structure)来管理对象的生命周期。一个控制块维护了一个引用计数,及其他必要的对象本身的信息.
void good() {
auto p{new int(10)}; //p is int*
std::shared_ptr<int> sp1{p};
//Create additional shared_ptr from an existing shared_ptr
auto sp2{sp1}; //OK. sp2 shares control block with sp1
}
从一个裸指针创建一个 std::shared_ptr<T> 会创建一个新的控制块。从一个裸指针创建多个 std::shared_ptr<T> 实例会造成严重的后果:
void bad() {
auto p{new int(10)};
std::shared_ptr<int> sp1{p};
std::shared_ptr<int> sp2{p}; //! Undefined Behavior
}
因此,我们需要一个机制能够达到我们的目的(捕获并保留一个指向当前对象本身的 std::shared_ptr<Processor> 实例).
这就是 std::enable_shared_from_this<T> 存在的意义,以下是修改后的类 Processor 实现
class Processor : public std::enable_shared_from_this<Processor> {
//..same as above...
};
void Processor::processData(const std::string& data) {
//shared_from_this() returns a shared_ptr<Processor>
// to this Processor
executor->execute([self = shared_from_this(), data]() {
//Executes in an Executor thread asynchronously
//'self' is captured shared_ptr<Processor>
self->doProcessAndSave(data); //OK.
});
}
self = shared_from_this() 传递的是一个合法的 std::shared_ptr<Processor> 实例,合法的类 Processor 对象的引用.
std::enable_shared_from_this<T> 的实现类似:
template<class T>
class enable_shared_from_this {
mutable weak_ptr<T> weak_this;
public:
shared_ptr<T> shared_from_this() {
return shared_ptr<T>(weak_this);
}
//const overload
shared_ptr<const T> shared_from_this() const {
return shared_ptr<const T>(weak_this);
}
//..more methods and constructors..
//there is weak_from_this() also since C++17
template <class U> friend class shared_ptr;
};
enable_shared_from_this 包含了一个 std::weak_ptr<T> 指针,这正是函数 shared_from_this 返回的内容。注意,为什么不是 std::shared_ptr<T>? 因为对象包含自身的计数引用会导致对象永远不被释放,从而发生内存泄漏。上述代码中 weak_this 会在类对象被 std::shared_ptr<T> 引用时赋值,也就是std::shared_ptr<T> 实例的构造函数中赋值,这也是为什么类 enable_shared_from_this 的最后,其被声明成为了 shared_ptr 的友元.
到此,关于 std::enable_shared_from_this<T> 的介绍就结束了.
https://en.cppreference.com/w/cpp/memory/enable_shared_from_this https://www.nextptr.com/tutorial/ta1414193955/enable_shared_from_this-overview-examples-and-internals 。
最后此篇关于何时/如何使用std::enable_shared_from_this?的文章就讲到这里了,如果你想了解更多关于何时/如何使用std::enable_shared_from_this?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
类中使用shared_ptr()的问题 当我们先定义一个指针,然后再用这个指针构造两个智能指针 int main() { int* pt = new int(); std::shared_
我有两个类A和B,其中B是A的子类。我需要两个类都可以使用std::enable_shared_from_this。 我尝试了这个: #include #include #include cla
我正在尝试在模板函数中使用 std::enabled_shared_from_this 函数,但在类中调用 shared_from_this() 时不断收到消息 bad_weak_ptr 错误。 te
我有以下类结构用于管理具有不同原型(prototype)的回调: class MethodHandlerBase: public std::enable_shared_from_this{ publi
我的类继承自多个基类,其中之一是 std::enable_shared_from_this .必须是第一垒吗? 假设以下示例代码: struct A { ~A(); }; struct B { ~B(
我找到的关于 enable_shared_from_this 的例子显示它通过继承使用。例如: struct Good : enable_shared_from_this { shared_p
在公开继承 enable_shared_from_this 并初始化类的对象后,在调用该类的另一个函数时,我在 Visual Studio 中调试时仍然可以看到 enable_shared_from_
我在阅读 Boost.Asio 示例时遇到了 enable_shared_from_this,在阅读了文档之后,我仍然不知道如何正确使用它。有人可以给我一个例子和解释什么时候使用这个类是有意义的。 最
这个问题在这里已经有了答案: What is the usefulness of `enable_shared_from_this`? (6 个答案) 关闭 8 年前。 我正在查看 shared_p
当我继承std::enable_shared_from_this,但是我创建了一个unique_ptr,std::enable_shared_from_this里面的weak_ptr也会被初始化吗当我
这个问题在这里已经有了答案: What is the usefulness of `enable_shared_from_this`? (6 个答案) 关闭 6 年前。 我是 C++11 的新手,我
我有一个对象 (Z),它派生自另外两个对象(A 和 B)。 A 和 B 都派生自 enable_shared_from_this<> ,分别enable_shared_from_this和 enabl
有没有办法阻止 shared_from_this() 调用堆栈分配的对象? 基类列表中的 enable_shared_from_this<> 是类用户的强指标,但有没有办法强制正确使用? 示例代码:
为什么我应该使用 enable_shared_from_this 因为我也可以通过简单的赋值获得相同的效果。 struct A : std::enable_shared_from_this { std
我正在使用 enable_shared_from_this然后从 Base 继承.尝试使用 shared_from_this() 时在 Derived的构造函数(不是初始化列表),我得到一个异常。原来
我有一个继承自 enable_shared_from_this 的类型,以及从该类型继承的另一种类型。现在我不能使用 shared_from_this 方法,因为它返回基类型,并且在特定的派生类方法中
我在阅读 Boost.Asio 示例时遇到了 enable_shared_from_this,在阅读了文档之后,我仍然不知道应该如何正确使用它。有人可以给我一个例子和解释什么时候使用这个类是有意义的。
要点回顾 继承自 std::enable_shared_from_this<T> 的类能够在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的
这个问题在这里已经有了答案: Double inheritance of enable_shared_from_this (3 个回答) 1年前关闭。 当我尝试运行此代码时,我得到 bad_weak_
我不知道这个问题是否适合 SO,但我们开始了: 启用 shared_from_this 时,是否会增加可执行文件的大小?解决 shared_from_this() 调用是否也需要太多时间? 查看文档,
我是一名优秀的程序员,十分优秀!