【问题标题】:Is there a never-null unique owner of heap allocated objects?堆分配的对象是否有一个永不为空的唯一所有者?
【发布时间】:2021-12-04 05:08:09
【问题描述】:

目前,我将std::unique_ptrs 的集合存储到堆分配的多态类型对象中:

struct Foo {
  virtual ~Foo() = default;
};
Collection<std::unique_ptr<Foo>> foos;

我需要的基本接口是将Foo 的所有者放入/取出foos。存储在foos 中的对象永远不应该是nullptr,所以我想用编译时检查替换运行时assert(owner_taken)。此外,我希望能够在可能预期可空所有者的上下文中使用非空所有者。

可能,我需要存储unique_ref 之类的内容,但我如何从foos 中提取一个?我不想要副本,我想要存储的对象本身,所以owner-&gt;clone() 不是解决方案。我也不能std::move(owner),因为之后“唯一引用”的状态将无效。

是否有干净的设计决策?

【问题讨论】:

  • 如果您不允许在永不为空的唯一所有者中出现非拥有状态,那么您将永远无法离开它,因为不会有任何有效状态。所以这样的类型总是不可移动的。这真的是你想要的吗?该集合是否适用于不可移动的类型?
  • 作为一种折衷方案,您可以制作自己的 nullptr-throwing unique_ptr,当它持有一个 nullptr 并尝试访问它所创建的 nullptr 时将抛出,或者如果尝试使用 nullptr 构造则抛出。 (例如,将其内脏从内部移出后,留下一个空壳。)
  • 但是你的集合可以处理不可移动的类型吗?例如。 std::vector不能。
  • @Eljay 恐怕它与我想避免的assert(owner) 太接近了。

标签: c++ architecture null heap-memory smart-pointers


【解决方案1】:

堆分配的对象是否有一个永不为空的唯一所有者?

标准库中没有这种类型。

可以实现这种类型。只需使用 unique_ptr 成员定义一个类型并将默认构造函数标记为已删除。您也可以将 std::nullptr_t 的构造函数标记为已删除,以便在编译时阻止 nullptr 的构造。

无论是从外部指针构造,还是在构造函数中分配,都没有办法在运行时检查 null。

【讨论】:

  • 参考文献呢? T&amp; 保证永远不会为空。
  • @passing_through 不是合法代码,但不幸的是很容易写illegal code
  • @user4581301 实际上,像您提供的示例是我在这里尝试使用引用而不是指针的原因:我可以确定它们不为空。如果我的问题有所有预期功能的答案,我可以将指针限制为仅在值实际上可以为 null 的情况下使用,因此始终检查这种特殊情况并不痛苦。
  • @passing_through 我强烈建议不要通过引用获取对象地址的所有权。太容易意外传递非拥有对象,例如自动对象。
  • @eerorika 你是对的:正是因为这种危险,我想要一个特殊的伪引用所有者类(而不仅仅是&amp;)来拥有堆上的对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 2014-09-01
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2021-09-27
相关资源
最近更新 更多