gpt4 book ai didi

c++ - 在遵循 pimpl 设计模式的类中实现移动语义的正确方法是什么?

转载 作者:行者123 更新时间:2023-11-30 00:51:16 25 4
gpt4 key购买 nike

做这件事的标准方法是什么?

让我们有一个class A有一个数据成员 std::unique_ptr<Impl> m_impl .

例如,类 A 的移动赋值运算符的内容应该是这样的吗?

m_impl = std::move(other.m_impl);

还是这个?

*m_impl = std::move(*other.m_impl);

第一种情况比第二种情况更有效率。但这会引发一些问题。

移动后other的m_impl数据成员为nullptr。被移出的对象是否应该在使用时抛出异常,或者只是让用户因取消引用 nullptr 而遇到运行时错误?

对于线程安全类,这也意味着所有 m_impl 的使用都需要同步。我不确定是否调用 std::unique_ptr的移动构造函数/赋值运算符是否是线程安全的。

最佳答案

前者。当您使用 unique_ptr 时,您这样做可能是因为对象本身可能首先不可复制和/或不可移动。因此,移动指针对象通常不是一种选择。

After moving, the m_impl data member of other is nullptr.

这是正确的从 std::unique_ptr 移出的。它需要支持销毁和重新分配,其他所有内容都是未定义的,与它的作用无关(空指针情况下的段错误)。

For thread-safe classes this would also mean that all m_impl usage needs to be synchronized.

除非明确说明,否则标准库不是线程安全的,只能重入。如果您的对象需要线程安全,您必须自己确保。

也就是说,如果一个线程移动一个它不是唯一所有者的对象,它会给其他线程带来问题,因为它们仍然会尝试在旧位置访问它。

您可以针对对象上的所有操作锁定移动操作,并定义移出对象上的操作语义以某种方式返回错误,但这听起来很痛苦,而且使用起来非常困惑。

线程安全的对象确实应该是异常的。您的目标应该是在线程之间移交对象,以便在任何给定时间只有一个人拥有该对象,并使所有共享数据不可变(可能的引用计数除外,这可以通过合理的性能 std::atomic 或构建于其之上的 std::shared_ptr

如果你真的需要一个线程安全的对象,它应该是不可移动的,或者应该像 handle 一样通过 std::shared_ptr 引用它的内部结构, 线程安全。

关于c++ - 在遵循 pimpl 设计模式的类中实现移动语义的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22604870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com