What are the best practices for passing a shared_ptr?
Currently I pass shared_ptr function arguments like so:
void function1( shared_ptr<TYPE>& value );
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
In controlled circumstances you can pass the shared pointer by constant reference. Be sure that nobody is concurrently deleting the object, though this shouldn’t be too hard if you’re careful about to whom you give references.
In general, you should pass the shared pointer as a straight copy. This gives it its intended semantics: Every scope that contains a copy of the shared pointer keeps the object alive by virtue of its “share” in the ownership.
The only reason not to always pass by value is that copying a shared pointer comes at a certain price on account of the atomic reference count update; however, this might not be a major concern.
Optional digression:
Since the main question has been answered, perhaps it is instructive to consider a few ways in which you should never use a shared pointer. Here is a little thought experiment. Let us define a shared pointer type
SF = std::shared_ptr<Foo>. In order to consider references, rather than passing function arguments let us look at the typeRSF = std::reference_wrapper<T>. That is, if we have a shared pointerSF p(std::make_shared<Foo>());, then we can make a reference wrapper with value semantics viaRSF w = std::ref(p);. So much for the setup.Now, everybody knows that containers of pointers are minefield. So
std::vector<Foo*>will be a nightmare to maintain, and any number of bugs arise from improper lifetime management. What’s worse conceptually is that it is never clear who owns the objects whose pointers the container stores. The pointers could even be a mix of pointers to dynamic objects, automatic objects, and garbage. Nobody can tell. So the standard solution is to usestd::vector<SF>instead. This is The Right Way to use the shared pointer. On the other hand, what you must never use isstd::vector<RSF>— this is an unmanageable monster that is actually very similar to the original vector of naked pointers! For example, it’s not clear whether the object to which you hold a reference is still alive. Taking a reference of the shared pointer has defeated its entire purpose.For a second example, suppose we have a shared pointer
SF pas before. Now we have a functionint foo(SF)that we want to run concurrently. The usualstd::thread(foo, p)works just fine, since the thread constructor makes a copy of its arguments. However, had we saidstd::thread(foo, std::ref(p)), we’d be in all sorts of trouble: The shared pointer in the calling scope could expire and destroy the object, and you would be left with a dangling reference and an invalid pointer!I hope these two admittedly fairly contrived examples shed a bit of light on when you really want your shared pointers to be passed around by copy. In a well-designed program, it should always be clear who is responsible for which resources, and when used right, the shared pointer is a great tool for the job.