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

Ste*_*ini 3 c++ heap interface 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Gui*_*cot 6

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

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

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

如果您只需要观察值,并且可能会改变它,那么您应该将非拥有句柄传递给您的函数.

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

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

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

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

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

  • @wphicks`std :: weak_ptr`仍然是共享所有权,但却是一个非拥有的句柄. (2认同)