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

rem*_*s4e 5 lambda move shared-ptr c++11 c++14

std::shared_ptr在lambdas中移动s 时我有一个奇怪的问题.我不确定它是否是一个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
}
Run Code Online (Sandbox Code Playgroud)

用命令c++ -std=c++14 -o test main.cpp && ./test产生类似的东西

1 0x55a49e601c30 1
3 0x55a49e601c30 1
2 0 0
Run Code Online (Sandbox Code Playgroud)

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

1 0x55a49e601c30 1
3 0x55a49e601c30 3
2 0x55a49e601c30 2
Run Code Online (Sandbox Code Playgroud)

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

我再次使用clang ++和g ++重现这一点.

怎么可能?

ken*_*ytm 16

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

std::move 无法移出const对象,因此创建了一个副本.

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

auto lambda = [ptr]() mutable {
//                    ^~~~~~~
Run Code Online (Sandbox Code Playgroud)

  • * std :: move无法移出const对象*在技术上不正确,如果将移动ctor声明为`X(const X &amp;&amp;);`,则可以“移出”`const`对象`X`。为什么有人想要做我不知道的疯狂事情,但是从技术上讲是可行的:现场示例[here](http://coliru.stacked-crooked.com/a/be6915b8c23d6736)。 (2认同)