2017-10-09 67 views
2

在以下示例中,捕获列表中使用[this]与捕获列表中使用捕获引用[&]相反,如图所示,有什么区别?我已经试过并且他们产生相同的输出。当在类中使用时,lambda捕获列表中的[this]和[&]是否等效?

#include <iostream>               

class Test {                 
public:                  
    int x = 2;                 
    void test1(void) { std::cout << "test1" << std::endl; };     

    void test_lambda(void) {             
     auto lambda = [&]() {            
      std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl; 
      this->test1();               
     };                 

     lambda();                
    }                   

protected:                 
    int y = 3;                 

private:                  
    int z = 4;                 
};                   

int main() {                 
    Test t;                 
    t.test_lambda();               
} 

在C++编程语言,Stroustrop说:

Members are always captured by reference. That is, [this] implies that members are accessed through this rather than copied into the lambda. 

这似乎在暗示,他们可能意味着同样的事情。如果是这样的话,为什么我们需要[这个]?

+0

&可用于特定变量 –

+2

始终使用您可以使用的最不强大的捕获。这不仅让当地的推理更容易,但你也可能在一段时间避免出错一次 – KABoissonneault

回答

2

根据cppreference

[&]捕获由参考通过引用和当前对象拉姆达的主体中使用的所有的自动变量如果而使用存在

[此]将捕获只有this指针。

当你在范围有自动变量这会有所不同,e.g:

struct Test { 
    void run() { 
    int y = 2; 

    // all automatic variables are accessible, both local and members 
    auto l1 = [&](){ cout << x << " " << y << endl; }; 
    l1(); 

    // y is not accessible, x is only because it's a member 
    auto l2 = [this]() { cout << this->x << endl; }; 
    l2(); 
    } 

    int x = 1; 
}; 

int main() { 
    Test t; 
    t.run(); 
} 

那么,我们为什么需要它?

允许捕获[this]与允许捕获任何其他指针相同。

为什么不总是捕获所有的自动变量?有几个原因,其中包括:

  • 封装:有时候,你不希望拉姆达熟悉其他值
  • 灵活性:有时候,我们需要复制一些价值观和通过它们其中的一些参考

注:使用&不会引入额外的性能开销捕获所有的自动变量,因为编译器只传递ŧ他在lambda中使用的变量。

+0

回复:“表演”,从cppreference报价意味着只有使用的变量被捕获。这对性能没有影响,因为如果捕获的数据少于编译将失败的数据。 –

+0

@DanielH,感谢您的提示,我已经错过了 –

1

&捕获范围内引用的所有变量。试想一下:

void test_lambda(void) {             
    int dummy = 42;     // capture dummy ?!? 
    auto lambda = [&]() {    // yes         
     std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl; 
     this->test1(); 
     std::cout << dummy;   // ok here              
    };                 
    lambda();                
} 

[this]不会捕捉局部变量意志[&]

+0

的问题是“自'[b]'比'更强大[这]',为什么我们需要'[这]'根本?“ –

+1

@RaymondChen因为你不希望捕捉到的东西,你不希望捕捉 – user463035818

+0

@RaymondChen考虑到这是不是问题,问题还没有被修改,你在哪里得到这个报价?我以同样的方式阅读它tobi303,因为问他们是否相同,如果不是他们有什么不同。 –

1

捕捉到成员的唯一方法是通过捕获this

  • 明确[this](){ member = 42; }
  • 含蓄地捕获由价值[=](){ member = 42;}
  • 含蓄地捕获参考[&](){ member = 42; }

以下是非法

  • [&member](){ member = 42; } // illegal
  • [member](){ std::cout << member; } // illegal

然后根据您的打算表示捕获的限制,你可能会被明确或不进行选择,避免reference捕获(以避免可能悬空参考)...

+0

我没有检查的标准,所以也许这是一个编译器扩展或东西,但经验'[&成员=成员(){/*...*/ }'工作得很好。 –

+0

@DanielH:这声明了一个*“已命名的lambda成员”*由变量初始化。我不会说它是一个成员的捕获(同样,对于'auto&ref = member; [&ref](){/ * ...* /}'),对我来说,这只是一个初始化。 – Jarod42

+0

它被称为捕获任何一种方式,在这种情况下,它是对同一个变量的引用。我不确定在捕获和初始化引用之间你有什么区别;有两种行为不同的情况吗? –

0

使用[this]只将捕获this,而[&]捕捉this所有局部变量从封闭的范围。

struct example { 
    int foo; 

    example() { 
    int bar; 

    [this]() { 
     foo = {}; 
     bar = {}; // error: 'bar' is not captured 
    }(); 

    [&]() { 
     foo = {}; 
     bar = {}; 
    }(); 
    } 
}; 

您可以使用[this]如果您关闭将封闭范围内的外部调用,就像一个成员函数,因为所有的局部变量将被销毁。

struct example { 
    int value = 42; 

    example() { 
    frobnicate = [this]() { 
     std::cout << value << std::endl; 
    }; 
    } 

    std::function<void()> frobnicate; 
}; 

example x; 
x.frobnicate(); 

您可以使用[&]如果您关闭将封闭的范围内被调用,像一块本地代码,如局部变量仍然活着。

struct example { 
    int value = 42; 

    example() { 
    int values[] = {1, 2, 3}; 

    std::for_each(std::begin(values), std::end(values), [&](int& v) { 
     std::cout << v * value << std::endl; 
    }); 
    } 
}; 
相关问题