This is confusing, but basically what I've got is a class that has a callback function using the c++11 std::function and std::bind. Everything is working fine. But when I need to reset everything by reassigning the object, it seems the new object isn't getting all of the references correct. Here is an example program that demonstrates my problem:
#include <functional>
#include <list>
#include <iostream>
#include <string>
class OtherClass
{
public:
OtherClass() = default;
void RegisterCallback(std::function<void(void)> f) {
callback = f;
}
void PrintThings() {
callback();
}
std::function<void(void)> callback;
};
class MyClass
{
public:
MyClass() {
list_of_things.push_back("thing1");
list_of_things.push_back("thing2");
list_of_things.push_back("thing3");
list_of_things.push_back("thing4");
other_class.RegisterCallback(std::bind(&MyClass::MyFunction, this));
}
void PrintThings() {
MyFunction();
other_class.PrintThings();
}
void MyFunction() {
auto a = this;
for (auto& thing: list_of_things)
{
std::cout << thing << std::endl;
}
}
OtherClass other_class;
std::list<std::string> list_of_things;
};
int main()
{
MyClass my_class;
my_class.PrintThings();
my_class = MyClass();
my_class.PrintThings();
std::cout << "done" << std::endl;
}
It's a little confusing, but basically if you compile with debug flags and step through it, you'll find that the first time we call my_class.PrintThings() it prints them twice; once for the MyFunction() call and once for the other_class.PrintThings() call which calls MyFunction as a callback. Then, we replace the object with my_class = MyClass(), invoking a new constructor and all that. When we step through, we find that it prints the list on the call to MyFunction but not on the call to other_class.PrintThings(). MyFunction has a variable a that I'm using to see the address of the object; the second time through a has a different address depending on whether MyFunction was called as a callback from OtherClass.
In this example, the offending ghost object just has an empty list (presumably as a result of being destroyed) but in the actual program where I encountered this, it was filled with garbage memory and caused a segmentation fault. I also noticed some weird behavior with my debugger; when it reached the ghost object it wouldn't just step in or over, it would skip the function unless I put a breakpoint inside there.
What is going on? Why isn't the callback bound properly the second time through? Is there something special I need to do in the destructor or something? Am I missing some fundamental understanding of function pointers or std::bind?
Aucun commentaire:
Enregistrer un commentaire