How to pass shared_ptr to a mutable object as a parameter?

I want to pass an object using a smart-pointer reference to a function. A function can change the value of the object referenced, but cannot change the link itself. There are two obvious ways to handle this.

The first approach for passing the shared_ptr value by value is a link, therefore, by itself should not be passed by reference. The obvious problem with this is copying the link, which involves some overhead for counting.

void foo (shared_ptr<bar> p) 

The second approach is to pass shared_ptr via the const link - avoiding copying the shared_ptr instance, but instead implying that accessing the specified object requires two dereferencing layers instead of one.

 void foo (const shared_ptr<bar> &p) 

In practice, these theoretical overheads are usually trivial and irrelevant. Which tells me that instead of choosing one approach or another for each individual case, I should almost always follow standard conventions. This leads to the question ...

Is there a standard agreement for which of these approaches should I choose? If so, what is the traditional choice?

EDIT . It is probably worth mentioning - one of the reasons for considering the buy-in-constant-reference case is that there is already an agreement that most instances of the class are / by value, and shared_ptr is a class. Of course, this is not a heavy class (the cost of copying is small), so the reasons for this older agreement may not apply.

+7
source share
4 answers

Always pass shared_ptr by value. If you pass the link, you may run into the problem that calling the function of an object controlled by shared_ptr might just reset, and now you have a dangling pointer. If you pass by value, you will make sure that the object will withstand the current function call.

See here for much more information.


Example:

 #include <memory> #include <iostream> std::shared_ptr<int> ptr(new int(42)); void foo(){ ptr.reset(); } void bar(std::shared_ptr<int> const& p){ foo(); std::cout << *p; } int main(){ bar(ptr); } 

This should be done with a pinch of salt. It can be adapted to prove that no type should be passed through a const link - see, for example, http://ideone.com/1IYyC , which was indicated by Benjamin Lindley in the comments.

However, more complex versions of these kinds of problems arise by chance in practice. That is why, for example, why we are warned that iterators (as well as return values ​​of a reference constant) are invalid using methods that mutate the specified container. These rules are simple enough to be followed in general, but sometimes more indirect and unexpected examples can catch people by surprise.

In this case, it is better to avoid an extra layer of links when it is not required.

+13
source

If the function manipulating the object should not be relevant if the object is contained in a smart pointer. He must accept T& . Free functions that manipulate values ​​are considered bad. Taking an object by reference to const and returning a new value can be cleaner.

0
source

I walked by const & based on the idea that somewhere in the call stack someone should have a copy of shared_ptr, and therefore his life is guaranteed for all of my execution.

In case you are executing another thread, you need a copy - and in this regard, anyone who stores shared_ptr (and not just uses it for the duration of his method) should keep a copy, not a link.

And now that I have written that I will go and read why people seem to support the opposite mentality.

0
source

An example of what @Xeo said:

 void foo(shared_ptr<bar> &p) { p.reset(); // ref_count == 0; memory is freed. } shared_ptr<bar> p(new bar); // ref_count == 1 foo(p); 

This does not happen for const shared_ptr<bar> &p .

-one
source

All Articles