std :: unique_ptr和std :: shared_ptr作为虚函数的参数

时间:2017-07-26 18:04:41

标签: c++ interface heap shared-ptr unique-ptr

我正在设计一个基于virtual方法的C ++类接口,以便能够提供可扩展性点。

许多这些公共方法需要heap分配的对象作为参数。

由于我正在使用现代C ++模式,我计划使用std::unique_ptrstd::shared_ptr,但我对它们都有疑问。

使用std :: unique_ptr它看起来像这样:

class IFoo {
  virtual void doSomethingWithUser(std::unique_ptr<User> user) = 0;
}

强制调用者提供std::unique_ptr有缺点:

  • 调用者无法对提供的用户执行任何操作,因为必须移动
  • 如果任何doSomethingWithUser实现需要将用户存储在某个容器中,则无法从std::shared_ptr构建

对所有公共方法使用std::shared_ptr可以解决问题,但我们必须支付额外的内存空间加上引用计数的原子增量和减量。

我可以遵循任何经验法则吗?

1 个答案:

答案 0 :(得分:6)

如果doSomethingWithUser不需要所有权,则不应将其转移到此方法。

实际上,复制共享指针或移动唯一指针会有效地转移资源的所有权。

您的函数参数应反映您对已传递资源的假定所有权的意图。

如果你只需要观察这个值,并且可能会改变它,你应该将一个非拥有句柄传递给你的函数。

如果你需要保持资源的存活并且可能删除它,那么你应该传递一个拥有句柄,无论它是否是共享的唯一所有权。

在你的情况下,函数的名称告诉我你需要“与用户做某事”,而不包含它通过调用者的生命周期。所以你应该传递一个非拥有的句柄。该句柄可以是User*User&,甚至是std::reference_wrapper<User>boost::optional<User&>,具体取决于您的需求。

您的界面确实应该表达对象应该能够做什么,并且确实强制执行每个函数应该采用的参数,但是您的界面还应该表达它对其参数的所有权。

我通常更喜欢引用,因为它们确保它不能为空并且在自动存储中与对象一起使用。有些人可能会说他们更喜欢原始指针作为非null非拥有句柄,但我强烈反对,因为它们强制&object语法并允许null。

非拥有原始指针没有任何问题。但是,不应该在现代C ++中使用原始拥有指针。