Koban
Koban

Reputation: 523

What is the preferred way to pass this std::shared_ptr as a function argument?

I have a very basic question about std::shared_ptr. If I have some

std::shared_ptr<A> p;

, where A is some class defined in my code, what is the preferred way to pass this std::shared_ptr as a function argument? Does it make a sense to define my functions that does something with the instance of class A like this:

void func(A &a);

and pass *p to these functions, and then convert 'a' back to std::shared_ptr with shared_from_this() if needed? Is there a reason to do so and what is the common practice? Or I should pass shared_ptr as the argument like this:

void func(std::shared_ptr<A> p); //thread safe
void func(const std::shared_ptr<A> & p); //not thread safe

In the most functions in my project I can use both alternatives, but my colleague said that the first alternative is better because the reference (A&) is always better than a pointer (shared_ptr or A*), because the reference semantics implies that the argument is not null.

Upvotes: 0

Views: 420

Answers (1)

JohnB
JohnB

Reputation: 13713

If you already have a shared pointer, it does not make sense not to pass the shared_ptr, yet create a new one by shared_from_this. That's simply complicated and does not earn you anything.

The usual advice is passing objects by value if the function needs to make a copy anyway (e.g. for storing the object) and passing by const reference if the function only needs to "view" the object.

This also applies to shared pointers.

Hence, e.g.

// Here func in the end needs a copy of the shared_ptr, so pass by value
// the caller can decide whether he wants to move or a copy it in
struct Example {
  shared_ptr<A> m_a;
  void func (shared_ptr<A> a) {
     m_a = move (a);
  }
};

// Here func needs only a reference, so only pass a reference
void func (shared_ptr<A> const & a) {
   a->callme ();
}

// If func needs to see only an object of type A, i.e. does not
// need a pointer, it makes
// more sense to pass an A & or A const &
void func (A const & a) {
   a.callme ();
}

I cannot imagine a situation where passing a shared_ptr by reference would imply problems with thread safety that could be avoided by passing by value. Of course, you should avoid holding a reference to a shared pointer in a thread that does not hold a copy of the shared pointer anywhere. Yet as soon as the thread has a copy of the shared pointer, you can pass references to that shared pointer freely within this thread.

Upvotes: 1

Related Questions