Let's say we have the following class:
Class MyClass
{
void func();
std::shared_ptr<std::function<void()>> getFuncPointer(); // returns pointer to func()
};
Let's say there is an object of some other class (let's call it objectB) that owns a shared_ptr to an object (objectA) of type MyClass. Assume objectB is the only owner/user of objectA and no one else has access to objectA.
What happens in the following sequence:
objectBcallsobjectA->getFuncPointer()and stores the returnedshared_ptr.objectBcallsobjectA.reset()
Question: Does objectA's destructor get called?
If objectB did not have the shared_ptr to one of objectA's methods, the answer will obviously be yes.
What I am not sure of is the effect of objectB acquiring a shared_ptr to one of objectA's methods.
If the answer is YES:
If objectA gets destructed, but another thread is still in func() via the function pointer, then what happens if we access a member variable? Seems problematic because objectA is gone along with its members.
If the answer is NO:
Seems problematic since I don't see how a shared_ptr to a member function can possibly keep the entire object alive. The function pointer knows nothing about the encompassing object, right?
Both scenarios seem problematic so that's why I am not sure which is the correct answer.
The answer is YES: an object can and will be deleted even if there's a
std::shared_ptrthat indirectly relies on it. By creating astd::shared_ptrto a given object (in this case a function), you're keeping that object around as long as it has a shared owner, so you have to promise that the object is valid for that long. If you break that promise, things will go wrong.It's not really any different from having an object O1 that holds a pointer to an object O2, and then
delete-ing O2 while O1 is still around. Even if O1 itself is held viastd::shared_ptr, that doesn't preserve O2.Unlike many languages, C++ makes no attempt to be "safe". It's very easy to write code that invokes undefined behavior; an important part of working in C++ is avoiding doing so.
std::shared_ptris a tool to help you write safe code, but it doesn't stop you from writing unsafe code.There's actually no such thing as a
shared_ptrto a method. In your case, you have ashared_ptrto an instance ofstd::function<void()>. An instance ofstd::functionholds a callable object (its "target"), but theshared_ptritself doesn't know anything about that target, doesn't own it, and can't/won't keep it alive.Additionally, although an instance of
std::functioncan hold a pointer to a member function, that can't be the situation in your case, because a pointer to a member function takes thethispointer as an argument, rather than implicitly depending on a specific instance; so if that were what you have, it would be astd::function<void(MyClass*)>rather than astd::function<void()>, and it wouldn't care if any particular instance ofMyClasshad been deleted. Rather, yourstd::functionprobably holds the result of a lambda expression, and that lambda probably holds a pointer to your instance ofMyClass. If so, then that's not an owning pointer, so, again, it won't keep the instance alive.Some docs you might want to look at:
std::function: https://en.cppreference.com/w/cpp/utility/functional/function