从技术角度来看,为什么不能在构造函数中使用 shared_from_this?

51

《C++标准库》的第91页中,我读到了有关shared_from_this()的内容:

问题在于,shared_ptr将自己存储在Person基类的私有成员enable_shared_from_this<>中,在 Person 构造函数结束时

书中相关的代码片段如下:

class Person : public std::enable_shared_from_this<Person> {
   ...
};

我不理解这两件事:

  1. shared_ptr 存储了谁?
  2. Person 构造函数结束时,它是如何将自己存储在任何地方的?我认为 Person 的构造函数以由我编写的最后一条语句结束。

我知道有一个尚未初始化的weak_ptr

编辑: 感谢Angew! 在创建第一个指向 Personshared_ptr之后,shared_from_this 才会起作用。 这个 shared_ptr 将检查 Person 类是否继承了 enable_shared_from_this,如果是,则初始化其内部的 weak_ptr


4
我没意识到你可能只是在请求这些笔记 - Marco A.
@MarcoA。太好了,这些笔记真的很有帮助! - Yola
2个回答

73
理由很简单:在对象X中,enable_shared_from_this通过使用指向对象X的第一个shared_ptr的副本来初始化隐藏的weak_ptr。然而,要使shared_ptr能够指向X,X必须已经存在(它必须已经构造)。因此,在运行X的构造函数时,还没有enable_shared_from_this可以使用的shared_ptr。
考虑下面这段代码:
std::shared_ptr<Person> p(new Person());
在调用shared_ptr的构造函数p之前,必须先计算它的参数。该参数是表达式new Person()。因此,在p的构造函数开始之前,Person的构造函数已经运行了——在任何shared_ptr对象可以绑定到enable_shared_from_this之前。

1
“enable_shared_from_this” 的工作原理是通过使用指向对象 X 的第一个 shared_ptr 的副本来初始化一个隐藏的 weak_ptr。哪个过程负责初始化这个隐藏的 weak_ptr?它如何知道指向 X 的“第一个”shared_ptr是什么? - ivme
1
@Chad 请查看此处的注释以获取一些信息:http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - Holt
3
谢谢@Holt。看起来shared_ptr的构造函数负责初始化weak_ptr。只有那些使用原始指针(例如从调用new返回的指针)的构造函数执行初始化。复制构造函数则不会执行。由于只有第一个指向X的shared_ptr应该由原始指针构造(其他通常是复制构造),因此weak_ptr由指向X的第一个shared_ptr初始化。 - ivme

0
因此,在X的构造函数运行时,还没有shared_ptr可以供enable_shared_from_this使用。
但是,在调用make_shared的情况下,可以在类的构造函数工作之前/期间访问控制块以创建weak_ptr,因为它们是在同一分配的内存块中创建的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接