std ::在lambda中使用std :: shared_ptr移动

时间:2017-04-10 09:21:35

标签: c++11 lambda c++14 shared-ptr move

在lambdas中移动std::shared_ptr时我有一个奇怪的问题。我不确定它是否是一个bug,因为我可以用g ++ v6.3和clang ++ v3.9重现。

编译并运行以下程序时:

#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
}
使用命令c++ -std=c++14 -o test main.cpp && ./test

会产生类似

的内容
1 0x55a49e601c30 1
3 0x55a49e601c30 1
2 0 0

但是,将编译命令更改为c++ -std=c++14 -o test main.cpp -DLAMBDA会使执行打印无法解释:

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

因此,似乎std::move(move)在lambda内部执行时,实际上不会导致移动shared_ptr,也不会阻止其引用计数器递增。

同样,我可以使用clang ++和g ++重现这一点。

这怎么可能?

2 个答案:

答案 0 :(得分:15)

lambda中捕获的变量ptr默认为const,即ptr的类型为const std::shared_ptr<int>

std::move无法移出const对象,因此会创建副本。

如果你真的想移动它,必须允许ptr变为可变:

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

答案 1 :(得分:0)

如果要在lambda中移动捕获的ptr,则需要通过引用捕获它,如下所示:

auto lambda = [&ptr]() {

如果你想移动属于lambda的ptr副本,你必须遵循kennytm回答。