如果非捕获的局部变量存在,为什么不能在Lambda中使用不合格的成员变量?

时间:2017-05-20 18:45:47

标签: c++ lambda language-lawyer shadowing

简单示例:

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中捕获。唯一有意义的xFoo的成员变量。

问题:这是预期的行为,如果是这样,请解释原因吗?

2 个答案:

答案 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;
        }();
    }
};

希望这会有所帮助。