【问题标题】:Whether to pass shared pointer or raw pointer to a function是否将共享指针或原始指针传递给函数
【发布时间】:2021-03-10 02:37:52
【问题描述】:

情况

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

问题

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

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

【问题讨论】:

  • 如果函数与对象的所有权有关,它应该接受一个共享指针。如果不是,则接受原始指针或引用。
  • @n.'pronouns'm。只有当智能指针不(ab)用作业务对象时,该建议才有效,而且在 OP 的代码中似乎就是这种情况——“我的客户端代码中都有智能指针”。在这种情况下,传递业务对象(即智能指针)似乎是更简洁的方法。更好的方法是让客户端代码处理正确封装的对象,而不是 std::shared_ptrs。
  • 如果你会通过const std::shared_ptr&lt;&gt;&amp;,那么从性能上看没有区别。引用计数的工作原理完全相同,因为计数器不会增加。但是如果你将std::shared_ptr按值传递,那就有区别了。

标签: c++ performance pointers memory


【解决方案1】:

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

还有一些其他的选项,比如weak_ptr,但对于这个可能不值得一看。

因此,对于您的示例,我们可以看到 ThirdParty_DoStuff 没有所有权,因此我们也不会,因此您可以分别根据参数是否强制在引用和指针之间进行选择。

【讨论】:

  • @kakyo,很好!对Third 错字进行一些清理。我很高兴你正在努力使它成为一个很好的问答。
【解决方案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);

【讨论】:

  • 谢谢。关于我的断言线索的好建议。
猜你喜欢
  • 2015-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多