我正在设计一个基于virtual
方法的C ++类接口,以便能够提供可扩展性点。
许多这些公共方法需要heap
分配的对象作为参数。
由于我正在使用现代C ++模式,我计划使用std::unique_ptr
或std::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
可以解决问题,但我们必须支付额外的内存空间加上引用计数的原子增量和减量。
我可以遵循任何经验法则吗?
答案 0 :(得分:6)
如果doSomethingWithUser
不需要所有权,则不应将其转移到此方法。
实际上,复制共享指针或移动唯一指针会有效地转移资源的所有权。
您的函数参数应反映您对已传递资源的假定所有权的意图。
如果你只需要观察这个值,并且可能会改变它,你应该将一个非拥有句柄传递给你的函数。
如果你需要保持资源的存活并且可能删除它,那么你应该传递一个拥有句柄,无论它是否是共享的唯一所有权。
在你的情况下,函数的名称告诉我你需要“与用户做某事”,而不包含它通过调用者的生命周期。所以你应该传递一个非拥有的句柄。该句柄可以是User*
或User&
,甚至是std::reference_wrapper<User>
或boost::optional<User&>
,具体取决于您的需求。
您的界面确实应该表达对象应该能够做什么,并且确实强制执行每个函数应该采用的参数,但是您的界面还应该表达它对其参数的所有权。
我通常更喜欢引用,因为它们确保它不能为空并且在自动存储中与对象一起使用。有些人可能会说他们更喜欢原始指针作为非null非拥有句柄,但我强烈反对,因为它们强制&object
语法并允许null。
非拥有原始指针没有任何问题。但是,不应该在现代C ++中使用原始拥有指针。