我有以下代码:
#include <iostream>
class Foo
{public:
Foo() {}
int a;
};
int main()
{
Foo foo;
auto lambda = [=]() mutable { std::cout << foo.a; };
}
一切都很顺利,直到我需要为我的Foo类添加一个复制构造函数:
Foo(Foo& t) {}
它不再编译,并显示以下信息:
类'Foo': 没有可用的复制构造函数或已声明复制构造函数为“显式”
我将lambda设为可变,因为我不想捕获一个const Foo,但我认为发生的事情是lambda无法被复制。另一个编译器提供了更有用的错误消息:
错误:使用已删除的函数'main()::< lambda()>::< lambda>(main()::< lambda()>&&)'
和:
'main()::< lambda()>::< lambda>(main()::< lambda()>&&)'会被隐式删除,因为默认定义将是非法的:
但我真的不明白这是什么意思。那个被隐式删除的函数是lambda的移动构造函数吗?我不明白为什么只是为捕获的类(而不是lambda)添加一个复制构造函数就会发生这种情况。
这就是我对lambda/functor的看法:
class lambda
{public:
Foo foo; // <---- My captured variable/class
void operator()(){ std::cout << foo.a; }
}
那么将其中一个lambda表达式复制到另一个lambda表达式中需要调用Foo的赋值运算符或拷贝构造函数?我不明白仅Foo有一个拷贝构造函数是如何导致此失败的,或者什么是“不健全”的。我注意到的另一件事是,在lambda通过引用[&]捕获时没有问题。
编辑:在这个编译器上它不能编译:
https://www.jdoodle.com/online-compiler-c++/
我正在使用Visual Studio,但它无法编译。然而,当我创建一个更小的示例时,它可以编译,但仍会在错误下划线。在我的较大项目中,它无法编译。
MSVC
和clang-cl
编译器中无错误编译(使用C++17标准)。您使用的是哪个编译器和标准? - Adrian Mole