4 ms·
Related to the capture of this and exceeding its lifetime, I've been doing it thusly: class Foo : enabled_shared_from_this<Foo> { void start_callback()
by tlb 8y ago
Related to the capture of this and exceeding its lifetime, I've been doing it thusly:
class Foo : enabled_shared_from_this<Foo> {
void start_callback() {
auto thisp = shared_from_this();
function_taking_callback([this, thisp](int err) {
if (err) errFlag = true;
});
}
bool errFlag{false};
}
The idea is that thisp is captured in the lambda and extends the lifetime of this until the callback is destroyed. And because this is also captured you can refer to member variables implicitly.
- eklitzke 8y agoClever.
- jdsully 8y agoI've used this in the past, but I've had trouble with "phantom callbacks". Where the logic of the program assumes the object is gone, and it ends up changing program state unexpectedly. The problem with shared pointers is ownership is not clear - just because you don't segfault doesn't mean there's no bug.
- zelos 8y agoExactly. I've had endless arguments about that exact point with shared_ptr. IMHO, shared_ptr should be used as a last resort, where ownership of something truly is shared. Use unique_ptr for everything else. Just using it for convenience for things like callbacks will lead to weird, hard-to-debug bugs in more complex code.
- tsbinz 8y agoA possible problem with this is that now the callback keeps this alive. A possible solution (in some situations) is to use a weak pointer and check if the object is still alive before using the callback, but there's some additional work to make this work nicely ...
- quietbritishjim 8y agoIn some situations, that is indeed a problem. In other situations, that is exactly what you want. For example, say you are passing a message along a sequence of threads (e.g. read from database in one thread, CPU-bound processing in the next, write back to database in the third). In that case, you probably want the lifetime of the request object to exactly match the time where there is an outstanding callback alive (either being called it waiting in a thread's queue). The ownership model in that case is very clear: threads own queues which own callbacks which own shared pointers which own message handling objects.
- jcelerier 8y agowhy capture both this and thisp ? doing `thisp->errFlag = true;` would cost nothing and save 4/8 bytes. Also doing [thisp = shared_from_this()] would save a potentially expensive atomic increment & decrement which happens when copying the shared_ptr