weak_from_this() 在构造函数中的使用

11
我知道你不能在构造函数中使用shared_from_this。但是在构造函数中使用新的weak_from_this可以吗?根据cppreference的说明:

这是enable_shared_from_this的一个私有可变weak_ptr成员的副本。

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this/weak_from_this

我认为在构造函数中获取内部存储的weak_ptr副本没有问题,但我可能遗漏了什么,所以对此不确定。


为什么目的? - curiousguy
1
根据weak_ptr的定义,它实际上是问题“为什么调用shared_from_this会调用std::terminate”的重复。请参考我的答案https://dev59.com/6hz8s4cB2Jgan1zn-kEg#50302557。 - curiousguy
1个回答

10

您可以调用它,但weak_ptr通常是空的。

shared_from_this 的重点不仅仅是让一些 shared_ptr,而是获得一个与现有 shared_ptr 指针集共享所有权的 shared_ptr。而 weak_ptr 的重点是提供一种方法,以获取一个 shared_ptr,如果此时存在其他 shared_ptr 指向同一对象,则共享所有权,而不像直接存储 shared_ptr 一样扩展对象生命周期。所以如果没有指向该对象的 shared_ptr 指针存在,weak_ptr 就无法指向同一对象。

请注意,在正常使用中,当您执行以下操作时:

std::shared_ptr<MyClass> p(new MyClass);

顺序如下:

  1. 实现调用 operator new(sizeof(MyClass)) 来获取一些存储空间。

  2. 实现调用 MyClass 的构造函数来在该存储空间内创建一个对象。

    • 如果 MyClass 继承了 std::enable_shared_from_this 的特化版本,则它包含一个 std::weak_ptr 子对象。使用 weak_ptr 的默认构造函数创建一个空智能指针。
  3. 实现调用 std::shared_ptr<MyClass> 的构造函数来创建一个智能指针,将指向 MyClass 对象的指针传递给它。

    • shared_ptr 的构造函数检查指针是否指向继承兼容的 std::enable_shared_from_this 特化版本的类类型。如果是,则类对象内的 std::weak_ptr 子对象被重新分配为正在构建的 shared_ptr 的副本。

因此,在 MyClass 的构造函数内部,您将处于第 2 步。但是,shared_from_this()weak_from_this() 使用的内部指针直到第 3 步才变得有用。

[在 std::make_sharedstd::allocate_shared 中也会进行类似的 weak_ptr 重新分配。在这些情况下,标准并没有明确说明在创建完指向的对象后会分配 weak_ptr,但是如果实现要额外努力以某种方式神奇地对 weak_ptr 进行操作,则这将是非常不寻常和意外的。在构造函数中可以创建指向 thisstd::shared_ptr,以将其存储在其他变量或容器中等等(但如果使用默认删除器,请确保您知道对象实际上是使用标量 new 创建的!)。在此之后,构造函数内都可以使用 shared_from_this()weak_from_this() 并返回与已创建的 std::shared_ptr 相关联的内容。但这似乎与正常做事情的方式相反。


1
您可以在类构造函数中创建一个指向自身的 std::shared_ptr。如果构造函数抛出异常,那么就会崩溃! - curiousguy
3
我知道复制的 weak_ptr 最初会为空。问题在于我不理解 weak_ptr 的实际工作原理。我曾以为即使最初为空,weak_ptr 的副本一旦原始 weak_ptr 变得有效,它也会变得有效。就好像两个 weak_ptr 引用同一个指针,这个指针最初可能是 nullptr,但会在某个时候变得有效,所有引用该指针的 weak_ptr 也会变得有效。但事实并非如此。 - Björn M.P.

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