【问题标题】:Why do we need to pass const shared pointer as reference?为什么我们需要传递 const 共享指针作为引用?
【发布时间】:2019-12-14 14:11:37
【问题描述】:

在阅读开源代码时,我发现以下内容以两种不同的方式将共享指针传递给函数。

class A{A();};

typedef std::shared_ptr<A> A_Ptr;

void func1(A_Ptr a);

void func2( const A_Ptr& a);

使用 const 时将其作为引用传递的原因是什么?我了解 func2 的编写者并不期望该函数能够更改 a 中的任何内容。但是我们不能这样做const A_Ptr a吗?另外,我们不应该在 func1 中使用A_Ptr & a 传递它的原因是什么?

以上在代码中的出现:

Git:https://github.com/uzh-rpg/rpg_svo/

List of FramePtr in the code

void FrameHandlerMono::setFirstFrame(const FramePtr& first_frame)

void DepthFilter::addFrame(FramePtr frame)

【问题讨论】:

  • 谁说过我们“需要”?无论如何,如果您没有获得所有权,则应该传递引用或原始指针,而不是拥有智能指针。
  • 您的意思是专门针对 shared_ptr 还是您想知道为什么要普遍使用 const 引用?
  • boost 是什么? std::shared_ptr 你在哪里标记了你的问题?阅读How to create a Minimal, Reproducible Example
  • 通过常量引用而不是按值传递或按指针传递的所有常见原因。对于func2,不调用复制构造函数,并且更少的字节被压入/弹出到堆栈中。通过 const 引用传递,就像 func2 的情况一样,如果这样做有意义的话,您还可以传递一个临时引用:ala : func2(make_shared<Frame>())
  • @MichaelMahn 感谢您的评论。我添加了更多细节。

标签: c++ c++11 shared-ptr smart-pointers


【解决方案1】:

但是我们不能只做这个const FramePtr 框架吗?

当然可以,但随后会调用复制构造函数,这适用于较大的类型(比内置类型更大的任何类型),通常比通过引用传递更昂贵。这与shared_ptr 无关。如果您不需要副本并且不想更改它们,通常应该默认通过 const 引用传递任何对象。只有 int、float 或 char 等内置类型才能按值传递。

更有趣的是为什么func1 使用副本。最可能的情况是他无论如何都需要一份副本,因为他想在课堂上保留一个参考。我在您发布的 github 存储库中找不到您引用的确切文件。如果仍然不清楚,请将 func1 的函数体添加到问题中。

编辑:啊,我明白了。看起来他在这里按值传递的原因更多地与线程安全有关。没有阅读全文,否则shared_ptr 可能会被拥有的线程删除,如果他通过 const 引用传递。

这里例如 func 需要按值传递,否则指针可能会被主线程删除。可能是这样的,但更复杂:

#include <chrono>
#include <iostream>
#include <memory>
#include <thread>

using namespace std::chrono_literals;

struct S {
    S() {}
};

void
//This signature would be false
//func(std::shared_ptr<S> const& s)
func(std::shared_ptr<S> s)
{
    std::cout << s.use_count() << '\n';
    std::this_thread::sleep_for(2s);
    //use_count would be 0 here if we pass by reference
    std::cout << s.use_count() << '\n';
}



int
main(int argc, char**) {
    std::shared_ptr<S> s{std::make_shared<S>()};

    std::thread t{func, std::ref(s)};

    std::this_thread::sleep_for(1s);

    s.reset();

    t.join();

    return 0;
}

【讨论】:

  • 非常感谢您的友好解释! pass-by-const-reference 现在很清楚,但副本仍然不清楚。我在他使用副本的代码部分添加了更多链接。
  • 太棒了!我什至没有考虑线程。现在我知道应该如何使用 shared_ptr。谢谢!
猜你喜欢
  • 2012-06-05
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
相关资源
最近更新 更多