简单示例:
class Foo {
int x;
void bar(int x) {
[this]() -> void {
x = 6;
}();
}
};
这不能在GCC,Clang,MVC或ICC(see it live)上编译。如果我将void bar(int x)
更改为void bar(int y)
,或者我将x = 6;
更改为this->x = 6;
,那么它可以正常工作。
这对我没有意义。调用x
的局部变量bar
故意不在lambda中捕获。唯一有意义的x
是Foo
的成员变量。
问题:这是预期的行为,如果是这样,请解释原因吗?
答案 0 :(得分:1)
来自cppreference:
为了查找名称,确定其类型和值 这个指针和用于访问非静态类成员的主体 闭包类型的函数调用操作符在上下文中被考虑 lambda表达式。
在方法栏(int x)的主体中,标记“x”指的是方法的参数,而不是类的成员。该成员被隐藏。 [注意这肯定是编码不好的做法,但不是非法的]
如果你说x = 6
你当前有lambda定义,你会期望改变局部变量x
(即方法的pass-by-value-argument),不是会员x
,对吧?
因此,唯一的问题是lambda可以隐式捕获局部变量吗?我会说编译器非常清楚地解释它不能。
cppreference也在本声明中明确指出:
如果变量没有,则可以使用它而不被捕获 自动存储持续时间(即它不是局部变量或它是 static或thread local)或者如果它在lambda的主体中没有使用odr。
注意:使用odr意味着你必须知道变量的地址,而不仅仅是它的值。为变量赋值会计为使用它的odr。
考虑以下代码:
class Foo {
int george;
void bar(int washington) {
int martha = washington;
washington = 7;
int jefferson = washington;
int adams = martha;
george = 6;
[this, jefferson]() -> void {
this->george = 15; // legal because `this` is captured
jefferson = adams; // legal because jefferson is explicitly
// captured, and because adams is not
// odr-used, so adams can be captured
// implicitly.
martha = 9; // not legal because it is an odr-use
// of a local variable so martha is not
// implicitly captured.
}();
}
答案 1 :(得分:0)
你说的错误说:
错误:变量' x'不能在没有指定capture-default
的lambda中隐式捕获x = 6;
注意:' x'在这里宣布 void bar(int x){ ^ 注意:lambda表达式从这里开始 这个 - > void { ^ 警告:私人领域' x'未使用[-Wunused-private-field] int x;
这导致我的问题在于变量x
的定义(或更准确,重新定义)。您在bar()
之外将其声明为参数。以下代码编译给我(使用您展示的实时tool):
class Foo {
int x;
void bar() {
[this]() -> void {
x = 6;
}();
}
};
希望这会有所帮助。