当在类中使用时,[this]和[&]在lambda捕获列表中是等价的吗?

时间:2017-10-09 14:18:53

标签: c++ lambda

在下面的示例中,在捕获列表中使用[this]与在捕获列表中使用capture-by-reference [&]之间的区别是什么,如图所示?我试过了两个,他们产生了相同的输出。

#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. 

这似乎意味着他们可能意味着同样的事情。如果情况确实如此,为什么我们需要[这]?

4 个答案:

答案 0 :(得分:3)

根据cppreference

  

[&amp;]通过引用捕获lambda体中使用的所有自动变量,如果存在,则通过引用捕获当前对象

而使用[this]将仅捕获this指针。

当您在范围内有自动变量时,这会有所不同,例如:

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熟悉其他值
  • 灵活性:有时,我们需要复制一些值并通过引用传递其中一些

注意:使用&amp;捕获所有自动变量不会引入额外的性能成本,因为编译器只传递我们在lambda中使用的变量。

答案 1 :(得分: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]不会像[&]那样捕获局部变量。

答案 2 :(得分:1)

捕获成员的唯一方法是捕获this

  • 明确[this](){ member = 42; }
  • 通过值[=](){ member = 42;}
  • 进行隐式捕获
  • 通过引用[&](){ member = 42; }
  • 隐式删除

以下是非法的

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

然后,根据您打算表达捕获的限制,您可以选择是否明确,避免reference捕获(以避免可能的悬空引用)......

答案 3 :(得分:0)

使用if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer") { // TODO } else if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") { // TODO } 只会捕获[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(); ,就像一段本地代码一样,因为局部变量仍然存在。

[&]