In this code:
#include
#include
struct A {
A() { std::cout << "A::A(), this: " << this << std::endl; }
void call(auto lambda) const {
std::cout << "A::call() this: " << this << std::endl;
lambda();
}
};
int main() {
auto p{std::make_unique()};
p->call([p2 = std::move(p)] { std::cout << "From lambda" << std::endl; });
return 0;
}
I would assume that p->call(...) would dereference a nullpointer because the capture [p2 = std::move(p)] must be executed before the call and after the lambda has been constructed, p is set to null according to std::unique_ptr's move constructor (5) in https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr.html
Constructs a
unique_ptrby transferring ownership from u to *this and stores the null pointer in u
But somehow it seems that first the unique_ptr is dereferenced, the address temporarily saved, then the lambda is constructed and then A::call is called on the temporary address that was saved before the resources of p have been stolen by p2 during lambda construction.
Why is that and where can I read this up?
Output with valgrind shows no errors:
valgrind --leak-check=full --track-origins=yes ./main
==841554== Memcheck, a memory error detector
==841554== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==841554== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==841554== Command: ./main
==841554==
A::A(), this: 0x4e4b080
A::call() this: 0x4e4b080
From lambda
==841554==
==841554== HEAP SUMMARY:
==841554== in use at exit: 0 bytes in 0 blocks
==841554== total heap usage: 3 allocs, 3 frees, 74,753 bytes allocated
==841554==
==841554== All heap blocks were freed -- no leaks are possible
==841554==
==841554== For lists of detected and suppressed errors, rerun with: -s
==841554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)