我使用的一些第三方 API 可以使用原始指针,但我的客户端代码中到处都有智能指针。
当我想围绕 API 编写包装函数时,我面临一个问题:是否传递共享指针或其原始指针作为参数。
像这样:
智能指针版本
// my wrapper
void MyWrapper(const std::shared_ptr<MyClassA>& pInObj, std::shared_ptr<MyClassB>& out_pOutObj) {
ThirdParty_DoStuff(pInObj.get(), out_pOutObj.get());
}
// my client code
auto inObj = std::make_shared<MyClassA>();
auto outObj = std::make_shared<MyClassB>();
MyWrapper(inObj, outObj);
原始指针版本
// wrapper
void MyWrapper(MyClassA* pInObj, MyClassB* out_pOutObj) {
assert(pInObj && out_pOutObj);
ThirdParty_DoStuff(pInObj, out_pOutObj);
}
// client code
auto inObj = std::make_shared<MyClassA>();
auto outObj = std::make_shared<MyClassB>();
MyWrapper(inObj.get(), outObj.get());
我认为,如果有一天该函数必须与其他类型的内存管理一起使用,那么第二个版本的可重用性更高。
我建议使用引用/原始指针,具体取决于您是否想传递
nullptr
。为什么?尽可能少地通过是一个很好的指南 - 如果您不需要增加引用计数或做任何特定的事情 shared_ptr
通过它不是必需的,并且可能会产生误导。
关于你的问题 - 如果包装的 API 可以处理
nullptr
,那么两者都相当安全。如果没有(这是您的assert
建议的),参考资料会更安全。
由于您通过引用传递,所以引用计数对于所有方法都将以相同的方式工作。如果您按值传递,则会增加函数调用的引用计数。
总而言之,我建议的解决方案:
// wrapper
void MyWrapper(MyClassA& pInObj, MyClassB& out_pOutObj) {
ThirdParty_DoStuff(&pInObj, &out_pOutObj);
}
// client code
auto inObj = std::make_shared<MyClassA>();
auto outObj = std::make_shared<MyClassB>();
MyWrapper(*inObj, *outObj);