【问题标题】:Is there unique_from_this()? Or how return unique_ptr from class inherited from enable_shared_from_this有 unique_from_this() 吗?或者如何从继承自 enable_shared_from_this 的类返回 unique_ptr
【发布时间】:2017-12-01 10:44:59
【问题描述】:

我希望我的构建器方法 Class::create() 返回 unique_ptr

为什么?

1) 这种设计不强制共享所有权(和原子锁)。 unique_ptr 非常高效,大小与void* 相同

2) 尽管如此,移动到shared_ptr 在类用户端仍然很容易(但仅当客户希望共享实例以获得多个所有权时)

所以。我只想为我正在使用的东西付费

但是。我需要一些类实例的方法来返回“this”指针。 如果我从enable_shared_from_this 继承类,我只使用return shared_from_this,但我认为它与唯一所有权无关

换句话说, 在类中某处创建的 unique_ptr(当然不使用 shared_from_this())会以某种方式与从这个 unique_ptr 创建的(潜在的)shared_ptr 相关吗?还是会导致双重删除问题?

【问题讨论】:

  • TBH 我不确定这是否有意义,因为this 可以很容易地放入unique_ptr,并且没有像shared_ptr 那样需要解决的问题。
  • 所以让我们看看 - 我返回了 unique_ptr 和一些 Owner 类。然后它移动到 shared_ptr 并将句柄提供给 OtherOwner 等其他类,以便它们保持强共享引用。但是我怎么能从类实例本身找到这个共享组呢?
  • 这没有任何语义意义。如果有一个对象可以调用这个成员函数,那么它已经被 something 拥有。在一般情况下,如何获得唯一的所有者?
  • @StoryTeller 确实如此。例如,我在 Controller 类中创建 Widget。我希望一个小部件能够创建层次结构。所以我用:shared_ptr widget1 = move(Widget::create()) 构建 Widget。然后 auto child = widget1->createChild() 每个孩子都应该收到父母的 shared_ptr -> 要在 Child 内的 weak_ptr 中转换。这意味着在 createChild 我必须访问 shared_from_this()
  • @StoryTeller-UnslanderMonica 我知道,有点晚了,但是:IMO,实际的问题是:enable_shared_from 这个本身是否经常在软件设计的错误地方使用? shared_from_this 的问题是:它以某种方式强制使用结构/类的方式(侵入性),这与类的“内部”语义重叠。用 enable_shared_from_this 标记类很快,但是一旦你想在不同的上下文范围内使用类,重新设计就会变得很混乱。

标签: c++ memory-management shared-ptr smart-pointers unique-ptr


【解决方案1】:

有unique_from_this()吗?

没有。

或者如何从继承自 enable_shared_from_this 的类中返回 unique_ptr

一般来说,不需要做任何特别的事情来将unique_ptr 返回到从enable_shared_from_this 继承的类。但请记住,shared_from_this 不得在 unique_ptr 拥有的实例上调用。因此,这是不安全的。

无论enable_shared_from_this 是否被继承,您都无法以安全的方式创建unique_ptrthis

1) 这种设计不强制共享所有权(和原子锁)。 unique_ptr 非常高效,与void* 大小相同

而这种缺乏共享所有权,使unique_ptr 快速,也是使unique_from_this 无法实现的原因。

【讨论】:

  • 现在清楚了,谢谢。一旦我获得了独特的所有权,作为班级客户,我有责任将其转移到共享所有权。然后,并且只有这样,类实例才能通过 shared_from_this() 参与其中。换句话说,如果我希望灵活地使用该类(通过共享或唯一构建器方法),我仍然可以返回唯一但继承自 enable_shared_from_this 类。但是在调用任何 shared_from_this() 之前,它的客户有责任从 shared 转移。
【解决方案2】:

换句话说,在类中某处创建的 unique_ptr(当然不使用 shared_from_this())是否会与从这个 unique_ptr 创建的(潜在的)shared_ptr 相关联?还是会导致双重删除问题?

shared_ptr 构造函数将检测您可公开访问的 enable_shared_from_this 基址,所以是的,如果 unique_ptr 正确释放其指针,您将不会有双重删除并且 shared_from_this() 成员将正常工作(但您将如果客户端在没有管理它的现有 shared_ptr 的情况下调用它,则获取 UB):

auto unique = Class::create();
auto shared = std::shared_ptr<Class>{ std::move(unique) }; // ok, pass ownsership to shared
auto shared_again = shared->shared_from_this(); // ok

auto unique2 = Class::create();
auto badly_shared = unique2->shared_from_this(); // nope, UB
auto badly_shared_again = std::shared_ptr<Class>{ unique2.get() }; // nope, double deletion coming ...

此外,由于 C++17 shared_from_this() 在从非共享实例调用时会抛出 bad_weak_ptr

【讨论】:

  • 我明白了。因此,唯一所有权与共享无关(例如,如果我只从 new 创建原始 * 指针)。但是如果我正确地将唯一移动/转换为共享,所有权将得到正确维护,我可以使用实例中的 shared_from_this() 。谢谢,现在说得通了!
  • @barney,是的,从 c++17 开始,如果客户端在不应该调用 shared_from_this() 时,你甚至会得到一个很好的异常......
猜你喜欢
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 2023-03-27
  • 2022-10-21
相关资源
最近更新 更多