Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a shared pointer by reference or by value as parameter to a class

Tags:

c++

shared-ptr

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);
}
like image 592
Signekatt Avatar asked Apr 11 '18 13:04

Signekatt


1 Answers

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.

like image 119
Mike Vine Avatar answered Sep 30 '22 12:09

Mike Vine