lambda是如何移动的
How is a lambda moved?
我不明白lambda是如何移动的。考虑以下代码:
#include <iostream>
#include <utility>
#include <string>
struct Foo // non-copyable type
{
Foo() = default;
Foo(const Foo&) = delete; // cannot copy
Foo(Foo&&) = default; // can move
};
auto lambda = [p = Foo()](){
std::string x{"lambda"};
std::cout << x << std::endl;
};
// auto copied_lambda = lambda; // cannot copy due to Foo non-copyable init capture
auto moved_lambda = std::move(lambda); // we moved it
struct Functor // "simulate" a lambda
{
std::string x{"functor"};
void operator()() const
{
std::cout << x << std::endl;
}
};
Functor functor; // initial functor object
auto moved_functor = std::move(functor); // moved it
int main()
{
lambda(); // why does it display "lambda" since it was moved?
moved_lambda(); // displays "lambda", was moved in, everything OK
functor(); // doesn't display "functor", was moved
moved_functor(); // displays "functor", was moved in, everything OK
}
正如您所看到的,我声明了一个Foo
不可复制(但可移动)的类,并将其传递给lambda
的init捕获,因此lambda
最终只被移动。lambda闭包声明了一个std::string
(它是可移动的)。接下来,我将lambda
移动到moved_lambda
中,因此我希望std::string
也会移动。然而,当我在main()
中调用lambda()
时,它仍然显示旧字符串,就好像它根本没有移动一样。
然后,我用函子"模拟"了Lambda,当将functor
移动到moved_functor
时,functor
中的初始string
也会移动,所以当我尝试在main()
中显示它时,我得到了一个空字符串。我对这种行为感到困惑,为什么会出现这种不一致?我本以为移动的lambda(内部只是一个函数对象)会移动其组件,而不是复制它们。我唯一的解释是lambda
中的局部变量是const
,所以我们没有移动它们,而是复制它们,但我不确定。是这样吗?
您的示例不完全相同。λ的正确模拟是:
struct Functor // "simulate" a lambda
{
void operator()() const
{
std::string x{"functor"};
std::cout << x << std::endl;
}
};
请注意,x
现在位于函数内部。这两个例子现在的行为是一样的:它们都打印它们的局部变量,即使它们被移动了。
解释很简单:内部变量不会被复制或移动,因为在复制或移动函子/lambda时它们不存在。它们被创建&当调用它们的operator()
时被销毁。
您的Functor
与lambda不一致。您的lambda实际上看起来像:
struct Functor // "simulate" a lambda
{
void operator()() const
{
std::string x{"functor"};
std::cout << x << std::endl;
}
};
希望这有助于弄清楚为什么你的"从lambda移动"仍然打印"lambda"
:Functor
的x
被从中移动,但lambda没有。
相关文章:
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- SendInput()鼠标移动计算
- Qt 如何使用鼠标移动事件移动视图
- 如何使用SFML鼠标移动分别移动多个图像
- 平台独立性:它与将源代码从一个操作系统移动到另一个操作系统有何不同
- C++11编译器何时会使RVO和NRVO优于移动语义和常量引用绑定
- 包含boost::可选对象的std::矢量对象是否可以移动?可移动助推::可选