Let’s say I have the following scenario where I define a callback function m_deleter.
class B {
public:
B() = default;
~B(){
if (m_deleter) {
m_deleter();
}
}
std::function<void()> m_deleter = nullptr;
};
class A {
public:
void createB(B& b) {
auto func = [this]() {
this->printMessage();
};
b.m_deleter = func;
}
void printMessage() {
std::cout << "Here is the message!" << std::endl;
}
};
And here is our main function:
int main() {
B b;
{
A a;
a.createB(b);
} // a falls out of scope.
}
Here is my confusion. When the stack instance a falls out of scope, is the memory not deallocated? How can the this pointer, used here in the callback: this->printMessage(); still point to a valid object?
When I run the above program, it prints:
Here is the message!
Edit:
Follow up question, is there any way for b to know that a has fallen out of scope and is no longer a valid object, and therefore should not call the callback?
>Solution :
It doesn’t. But due to the fact that in the method printMessage you don’t reference any fields from the class A, there is no crush. This is an UB however.
Here is the code that avoids this issue but demonstrates the correct behavior:
class A {
public:
void createB(B& b) {
auto func = []() {
A::printMessage();
};
b.m_deleter = func;
}
static void printMessage() {
std::cout << "Here is the message!" << std::endl;
}
};
No pointer, no references to any field, no need to track whether the instance is valid, no UB. If you need to access the data from A, you need a valid instance.