我已经远离严肃的C ++大约十年了。我正在重新回到目前,我正在开展一个项目,以完全熟悉C ++ 11。关于如何最好地传递std :: shared_ptr,我有一点存在的危机。
举一个简单的例子,采取以下设置:
class ServiceB {
public:
ServiceB() {}
};
class ServiceA {
public:
ServiceA(std::shared_ptr<ServiceB>& serviceB)
: _serviceB(serviceB) {
}
private:
std::shared_ptr<ServiceB> _serviceB;
};
class Root {
public:
Root()
: _serviceB(std::shared_ptr<ServiceB>(new ServiceB())),
_serviceA(std::unique_ptr<ServiceA>(new ServiceA(_serviceB))) {
}
private:
std::shared_ptr<ServiceB> _serviceB;
std::unique_ptr<ServiceA> _serviceA;
};
请注意,ServiceA需要引用ServiceB。我想将该引用保存在shared_ptr中。我可以做我在这里做的事情,这只是将shared_ptr作为参考传递下去,让std :: shared_ptr复制构造函数为我工作吗?这是否正确地增加了shared_ptr上的引用计数?
如果这不是最好的方法,那么传递std :: shared_ptr的常见“最佳做法”是什么?
答案 0 :(得分:13)
您应该在传递其他对象时准确传递共享指针。如果您需要存储副本(共享指针的副本,而不是指向的对象),请按值传递,然后移动到目标位置。
ServiceA(std::shared_ptr<ServiceB> serviceB)
: _serviceB(std::move(serviceB)) {}
或者,如果你不介意编写两个构造函数,你可以通过编写一个带有const引用并复制它的一个来保存一点性能(一次调用共享指针的移动构造函数),并且一个r值参考,然后移动它。
ServiceA(std::shared_ptr<ServiceB> const& serviceB)
: _serviceB(serviceB) {}
ServiceA(std::shared_ptr<ServiceB> && serviceB)
: _serviceB(std::move(serviceB) {}
答案 1 :(得分:3)
通过值传递(编译器非常擅长删除副本)或者通过const引用 - 非const引用,因为它使您看起来像是要修改参数。
同样对于新代码,请考虑使用unique_ptr
作为参数并在有意义的地方返回值,或者共享不属于合同的情况。 (您可以从shared_ptr
制作unique_ptr
,但反之亦然。)
答案 2 :(得分:2)
通过引用传递给非const。
当你不想这样做时,通过引用传递给你。
对const的引用在技术上只是对shared_ptr的微优化,但它没有坏处,它是类类型参数的通用约定,它只能减少一些纳秒。
另一个问题,因为C使用前置下划线来实现名称,所以最好在C ++中避免使用它,所以不要在前面添加下划线,而是将它放在最后。例如这是boost库中的惯例。或者只是使用其他约定。