是否将共享指针或原始指针传递给函数

问题描述 投票:0回答:2

情况

我使用的一些第三方 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());

问题

  • 在性能和内存安全方面哪种方法更好?
  • 两种方法之间的引用计数工作方式会略有不同吗?

我认为,如果有一天该函数必须与其他类型的内存管理一起使用,那么第二个版本的可重用性更高。

c++ performance pointers memory
2个回答
4
投票

我建议采用以下方法来查看类似这样的代码:

还有一些其他选项,例如

weak_ptr
,但对于这个来说,它可能不值得一看。

因此,对于您的示例,我们可以看到

ThirdParty_DoStuff
不获取所有权,因此我们也不会,因此您可以分别根据参数是否为强制在引用和指针之间进行选择。

编辑: 从 c++17 开始,您可以选择使用

optional
这现在也可以涵盖您有可选输出的情况。


2
投票

我建议使用引用/原始指针,具体取决于您是否想传递

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);

© www.soinside.com 2019 - 2024. All rights reserved.