A few day ago I asked how to save a callback function in a class. Now, I don't know how to save a callback function with referenced arguments. I'll give you an example.
By the way, I can't just put & signs on gameObjects like std::vector<GameObject>&gameObjects because my program will crash. I'm definitely missing something.
Converting the code you've posted to using references should pose no problem. It could only be a problem if the callback does anything strange with the gameObjects parameter, such as saving a pointer to it or one of its elements in a variable that outlives the call. E.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
std::vector<GameObject> *go;
int Update(std::vector<GameObject> &gameObjects, int a) {
//Escaping reference!
go = &gameObjects;
}
int main(){
//...
game.InitCallback(Update);
//(An update happens.)
//Is this valid or not? Impossible to know from the code you've shown.
go->clear();
}
An object of type std::function<T> stores a copy of the target callable object.
Of course, but you can run into problems if you bind by reference, or if your objects contain pointers to objects with automatic lifetimes, or stuff like that. Once you have a closure that may escape the scope where it was declared, it may become more difficult to figure out what needs to be done to maintain its validity throughout its lifetime.
OP has already said he's getting crashes with what seems perfectly reasonable code, so we don't know what he might be doing. Switching to std::function willy-nilly might only make things more complicated, not to mention more difficult to debug.
Those problems have nothing specific to do with std::function<>. Those problems (undefined behaviour) would be there whether or not the callable object was wrapped in a call wrapper.
The warning you gave was: "The lifetime of objects within an std::function is arbitrary."
Which is completely invalid.
An object of type std::function<T> stores a copy of the target callable object;
the life-time of that object not arbitrary, it has a well defined life-time.
This has undefined behaviour; but that is not because the the lifetime of objects within a std::vector<> is arbitrary.
"Arbitrary" in the sense that it may outlast the scope that created it for arbitrarily long, not in the sense that the lifetime is some uncertain quantity.
I would argue that yes, your example has undefined behavior precisely because a pointer's lifetime may be arbitrarily longer than the thing it points to. Any object that may contain pointers -- such as std::vector<T *>, std::list<T *>, std::tuple<T *>, lambdas that bind pointers, etc. -- is capable of producing escaping references.