我应该使用 shared_ptr 还是 unique_ptr

新手上路,请多包涵

我一直在使用 pimpl 成语制作一些对象,但我不确定是使用 std::shared_ptr 还是 std::unique_ptr

我知道 std::unique_ptr 效率更高,但这对我来说不是什么大问题,因为这些对象无论如何都是相对重量级的,所以 std::shared_ptr 的成本超过 std::unique_ptr 相对较小。

我目前正在使用 std::shared_ptr 只是因为额外的灵活性。例如,使用 std::shared_ptr 允许我将这些对象存储在哈希图中以便快速访问,同时仍然能够将这些对象的副本返回给调用者(因为我相信任何迭代器或引用都可能很快变得无效)。

但是,这些对象实际上并没有被复制,因为更改会影响所有副本,所以我想知道也许使用 std::shared_ptr 并允许副本是某种反模式或坏事。

这个对吗?

原文由 Clinton 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 577
2 个回答

我一直在使用 pimpl 成语制作一些对象,但我不确定是否使用 shared_ptrunique_ptr

绝对 unique_ptrscoped_ptr

Pimpl 不是一种模式,而是一种习语,它处理编译时依赖和二进制兼容性。它不应影响对象的语义,尤其是在其复制行为方面。

您可以在后台使用您想要的任何类型的智能指针,但它们 2 保证您不会意外地在两个不同的对象之间共享实现,因为它们需要有意识地决定复制构造函数和赋值运算符的实现。

但是,这些对象实际上并没有被复制,因为更改会影响所有副本,所以我想知道也许使用 shared_ptr 并允许复制是某种反模式或坏事。

它不是反模式,实际上是一种模式:Aliasing。您已经在 C++ 中使用了它,并带有裸指针和引用。 shared_ptr 提供额外的“安全”措施以避免死引用,但代价是额外的复杂性和新问题(注意会造成内存泄漏的循环)。


与粉刺无关

我知道 unique_ptr 效率更高,但这对我来说不是什么大问题,因为这些对象无论如何都是相对重量级的,所以 shared_ptr 的成本超过 unique_ptr 相对较小。

如果您可以考虑某些状态,您可能需要查看 Flyweight 模式。

原文由 Matthieu M. 发布,翻译遵循 CC BY-SA 2.5 许可协议

当您使用 shared_ptr (例如在容器中,然后查找它并按 返回它)时,您不会导致它指向的对象的副本,只是指针的副本参考计数。

这意味着如果您从多个点修改底层对象,那么您会影响 同一实例 上的更改。这正是它的设计目的,所以不是一些 _反模式_!

当传递 shared_ptr 时(正如评论所说),最好在需要的地方通过 const 引用和复制(通过增加引用计数)。至于退货,视情况而定。

原文由 Nim 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题