Passing a shared pointer by reference or by value

2019-04-05 16:27发布

问题:

Should a shared pointer be passed by reference or by value as a parameter to a class if it is going to be copied to a member variable?

The copying of the shared pointer will increment the refrence count and I don't want to make any unnecessary copies and thus ref count increments. Will passing the shared pointer as a refrence solve this? I assume it does but are there any other problems with this?

Passing by value:

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

Passing by refrence:

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

回答1:

Pass it by value then move it into the member:

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

This will be the most efficient in all cases - if the caller has a rvalue-reference then there wont be a single add-ref, if the caller has a value there'll be a single add-ref.

If you pass by const& you force an add-ref even in cases where its unnecessary. If you pass by value and then set without a std::move you may get 2 add-refs.

Edit: This is a good pattern to use if you've got a class where a move is significantly cheaper than a copy, and you have a function call which will always copy the instance passed in - as in this case. You force the copy to happen at the function call boundary by taking it by value, and then if the caller has a rvalue reference the copy need never happen at all - it will be moved instead.



回答2:

shared_ptr should be treated just like any other class when passing to functions. in this case you should pass to const reference.

why i wrote why i wrote Herb Sutter jump to min 21:50 https://www.youtube.com/watch?v=xnqTKD8uD64