通过引用或值作为参数将共享指针传递给类

Sig*_*att 10 c++ shared-ptr

如果共享指针要被复制到成员变量,是否应该通过引用或值作为参数传递给类?

复制共享指针将增加参考计数,我不想做任何不必要的副本,因此ref计数增量.将共享指针作为参考传递解决这个问题?我认为确实如此,但是还有其他问题吗?

价值传递:

class Boo {
public: 
    Boo() { }
};

class Foo {
public:
    Foo(std::shared_ptr<Boo> boo) 
        : m_Boo(boo) {}
private:
    std::shared_ptr<Boo> m_Boo;
};

int main() {
    std::shared_ptr<Boo> boo = std::make_shared<Boo>();

    Foo foo(boo);
}
Run Code Online (Sandbox Code Playgroud)

通过参考:

class Boo {
public: 
    Boo() { }
};

class Foo {
public:
    Foo(std::shared_ptr<Boo>& boo) 
        : m_Boo(boo) {}
private:
    std::shared_ptr<Boo> m_Boo;
};

int main() {
    std::shared_ptr<Boo> boo = std::make_shared<Boo>();

    Foo foo(boo);
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*ine 17

按值传递然后将其移动到成员中:

class Foo {
public:
    Foo(std::shared_ptr<Boo> boo) 
        : m_Boo(std::move(boo)) {}
private:
    std::shared_ptr<Boo> m_Boo;
};
Run Code Online (Sandbox Code Playgroud)

这在所有情况下都是最有效的 - 如果调用者有一个rvalue-reference,那么就不会有一个add-ref,如果调用者有一个值,那么就会有一个add-ref.

如果你经过,const&你甚至在不必要的情况下强制使用add-ref.如果你通过值传递然后设置没有a std::move你可能会得到2个add-refs.

编辑:这是一个很好的模式,如果你有一个类,其中一个移动明显比副本便宜,并且你​​有一个函数调用,它将始终复制传入的实例 - 如本例所示.通过按值取值来强制复制发生在函数调用边界处,然后如果调用者具有右值引用,则根本不需要复制 - 它将被移动.

  • 尽管如此,即便采取行动也不是免费的.对于简单函数`std :: shared_ptr <int> foo(std :: shared_ptr <int> arg){return std :: move(arg); ``,`g ++`生成六个内存访问:两个用于读取参数,两个用于使参数为空,两个用于构造结果.这对内存总线来说相当沉重(同时CPU也会歪着大拇指).当然,移动(本地缓存操作)比撞击原子引用计数(具有CPU间开销)更便宜,因此这种移动的使用是非常好的.然而,有些情况下,传递'const &`比移动更快. (4认同)