std::move 和 std::shared_ptr 在 lambda 中
std::move with std::shared_ptr in lambda
我在 lambda 中移动 std::shared_ptr
时遇到一个奇怪的问题。我不确定它是否是错误,因为我可以使用 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++ 重现它。
这怎么可能?
lambda中捕获的变量ptr
默认是const,即ptr
的类型是const std::shared_ptr<int>
.
std::move
无法移出 const 对象,因此创建了一个副本。
如果你真的想移动它,ptr
必须允许是可变的:
auto lambda = [ptr]() mutable {
// ^~~~~~~
如果你想在lambda中移动捕获的ptr
你需要通过引用来捕获它,如下:
auto lambda = [&ptr]() {
如果您想移动 ptr
属于 lambda 的副本,您必须遵循 kennytm 的回答。
我在 lambda 中移动 std::shared_ptr
时遇到一个奇怪的问题。我不确定它是否是错误,因为我可以使用 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++ 重现它。
这怎么可能?
lambda中捕获的变量ptr
默认是const,即ptr
的类型是const std::shared_ptr<int>
.
std::move
无法移出 const 对象,因此创建了一个副本。
如果你真的想移动它,ptr
必须允许是可变的:
auto lambda = [ptr]() mutable {
// ^~~~~~~
如果你想在lambda中移动捕获的ptr
你需要通过引用来捕获它,如下:
auto lambda = [&ptr]() {
如果您想移动 ptr
属于 lambda 的副本,您必须遵循 kennytm 的回答。