I have a strange issue when moving std::shared_ptr
s in lambdas. I am not sure if it is a bug or not, as I can reproduce with g++ v6.3 and clang++ v3.9.
When I compile and run the following program:
#include <iostream>
#include <memory>
void f(std::shared_ptr<int> ptr) {
std::cout << 3 << " " << ptr.get() << std::endl;
}
int main() {
auto ptr = std::make_shared<int>(42);
std::cout << 1 << " " << ptr.get() << std::endl;
#ifdef LAMBDA
auto lambda = [ptr]() {
#endif
f(std::move(ptr));
std::cout << 2 << " " << ptr.get() << std::endl;
#ifdef LAMBDA
};
lambda();
#endif
}
with the command c++ -std=c++14 -o test main.cpp && ./test
yields something like
1 0x55a49e601c30 1
3 0x55a49e601c30 1
2 0 0
However, changing the compilation command to c++ -std=c++14 -o test main.cpp -DLAMBDA
makes the execution print something I cannot explain:
1 0x55a49e601c30 1
3 0x55a49e601c30 3
2 0x55a49e601c30 2
So, it appears that the std::move(move)
, when performed inside a lambda, does not actually cause the shared_ptr
to be moved, nor does it prevent its reference counter to be incremented.
Again, I can reproduce this with clang++ and g++.
How is that possible?
The captured variable ptr
in a lambda is by default const, i.e. the type of ptr
is const std::shared_ptr<int>
.
std::move
cannot move out const objects, so a copy is created instead.
If you really want to move it, the ptr
must be allowed to be mutable:
auto lambda = [ptr]() mutable {
// ^~~~~~~