Std :: move with std :: shared_ptr in lambda

I have a strange problem when moving std::shared_ptr to lambdas. I am not sure if this is a mistake 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 gives 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 print run something that I cannot explain:

 1 0x55a49e601c30 1 3 0x55a49e601c30 3 2 0x55a49e601c30 2 

Thus, it turns out that std::move(move) , when executed inside the lambda, does not actually call shared_ptr to move, does not prevent its reference count from increasing.

Again, I can reproduce this with clang ++ and g ++.

How is this possible?

+5
source share
2 answers

The captured ptr variable in lambda is const by default, i.e. type ptr - const std::shared_ptr<int> .

std::move cannot move const objects, so a copy is created instead.

If you really want to move it, ptr should be changed:

 auto lambda = [ptr]() mutable { // ^~~~~~~ 
+15
source

If you want to move the captured ptr to lambda, you need to write it by reference, as shown below:

 auto lambda = [&ptr]() { 

If you want to move the ptr copy owned by lambda, you must follow kennytm's answer.

0
source

Source: https://habr.com/ru/post/1266545/


All Articles