5

Most questions on Stackoverflow are asking about shared_ptr should be passed by ref or by value. However my question is exampled like this:

class Foo;

void function1(Foo & ff) { ff.m_abc = 1024; }
void function2(const std::shared_ptr<Foo> & ff) { ff->m_abc = 1024; }

The function1 and function2 may use and change some part of ff.


My case here:

I have a need for calling a function with an arg *this or shared_from_this().

print(msg, *this);

or

print(msg, this->shared_from_this());

I can either use function1 or function2 style in my code for a function.

However, if I use function2 style, I need to implement Foo to inherit from std::enable_shared_from_this, but with function1 style, I do not need to.

I'm using this function in a single-threaded environment

Adam
  • 1,684
  • 1
  • 19
  • 39

2 Answers2

9

You only pass the shared_ptr to a function if the function cares about there being a shared_ptr, usually because it wants to keep a copy, or a weak_ptr.

Anything else just reduces applicability of the function for no gain.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • It will want to keep a copy at least for the duration of the function. In a multithreaded environment this may be an issue. I'm not sure I can agree with this answer. – John Dibling Jan 30 '14 at 14:38
  • 4
    It's the caller's responsibility to make sure that the references it gives to a function don't become invalid while the function is running. Anything else is insane. And if the caller has a `shared_ptr` on its stack, you're safe. – Sebastian Redl Jan 30 '14 at 14:39
  • And if the `shared_ptr` the source has can be modified by more than one thread, neither solution is safe. – Yakk - Adam Nevraumont Jan 30 '14 at 14:42
  • And if `function1` actually stores the pointer in a `vector (&ff)` which is used by a worker thread, what then? – John Dibling Jan 30 '14 at 14:43
  • 3
    @JohnDibling Then you shoot your developers for screwing up 3 ways from Sunday. Creating a `shared_ptr` from a reference? Bad. Creating a `shared_ptr` for a resource you did not create? Bad. Creating a `shared_ptr` for a resource you did not create that is `enable_shared_from_this` instead of calling `shared_from_this`? They better bring donuts. – Yakk - Adam Nevraumont Jan 30 '14 at 14:50
  • In multithreading environment, we should adopt `void function3(std::shared_ptr ff);` which copies the ptr and make sure it has at least one ref to the resource so that it'll not be deleted by other threads. – Adam Jan 30 '14 at 14:54
  • Every environment is multi-threaded, unless you plan to never reuse your code, ever. Are you saying we should not use references anymore? You use by-val parameters on functions that you start new threads with; those should be pretty easy to identify. And if you start a thread/async task for some existing function that takes by-ref, you just wrap it, possibly in a lambda. – Sebastian Redl Jan 30 '14 at 15:07
  • The comment on multi-threaded environments makes no sense to me. If the shared pointer exists in the caller, you don't need to make a new copy of it for the duration of the function. Reference is perfectly safe. Edit: @SebastianRedl perfectly commented above. – Joky Jan 30 '14 at 19:21
3

You should pass a shared_ptr if you want to share the ownership of the object with the function you're calling, that is if you want to make sure the object will be alive as long as the function needs it.

One case where this is important is if your function does an asynchronous operation, it might want to use your object once the operation is finished and by that time your object might have been deleted so if you passed by reference, that reference is dangling, while if you passed shared_from_this(), you are guaranteed that the life time of your object will be extended to as long as the function needs it. (Most code samples of boost::asio for example are based on this logic).

Drax
  • 12,682
  • 7
  • 45
  • 85