C ++ 11 lambda捕获`this`并按值捕获局部变量

Posted

技术标签:

【中文标题】C ++ 11 lambda捕获`this`并按值捕获局部变量【英文标题】:C++11 lambda capture `this` and capture local variables by value 【发布时间】:2018-05-04 21:39:06 【问题描述】:

下面的 lambda 函数捕获 this(因此 bar() 可以访问其实例变量)和局部变量 a,b,c

class Foo 
  int x, y, z;
  std::function<void(void)> _func;
  // ...
  void bar() 
     int a,b,c;
     // ...
     _func = [this,a,b,c]()  // lambda func
        int u = this->x + a;
        // ...
     ;
  
;

但如果我想捕获许多实例变量并希望避免在捕获列表中明确命名它们,我确实 似乎能够做到这一点:

     _func = [this,=]()  // lambda func
        // ...
     ;

我在= 后面的this, 处收到编译器错误:

  error: expected variable name or 'this' in lambda capture list 

如果我试试这个

     _func = [=,this]()  // lambda func
        // ...
     ;

我明白了

  error: 'this' cannot be explicitly captured when the capture default is '='

是否有按值捕获this 和其他所有内容的简写?

更新: [=, this] 作为 lambda 捕获是 new feature of C++20

【问题讨论】:

[=] 也不能捕获this 吗? 真的吗?天哪,它确实如此。我想我会删除我的问题。 我想 SO 希望我把这个问题留在这里......也许其他一些糟糕的编程灵魂(例如,曾经使用 [unowned self] 的 Swift 程序员)会发现它很有用。 [this,=] 将是一个令人困惑的矛盾修饰法,因为这是一个指向对象的指针..所以实际上您将通过引用捕获整个对象,这与值 [=] 的默认值冲突。 【参考方案1】:

正如 cppreference 所说:

[=] 通过复制捕获 lambda 主体中使用的所有自动变量,并通过引用捕获当前对象(如果存在)

【讨论】:

明显的 [=,this] 在 C++20 中添加。 en.cppreference.com/w/cpp/20【参考方案2】:

[*this,=] 通过c++17 中的值捕获两个局部变量对象。

[&amp;] 通过引用捕获局部变量,*this 通过引用或this(指针)通过值。

两种默认捕获模式都以相同的方式捕获this。只有在c++17 中才能更改。

【讨论】:

【参考方案3】:

[=] 已经按值捕获了this。看看下面的代码:http://cpp.sh/87iw6

#include <iostream>
#include <string>

struct A 
    std::string text;

    auto printer() 
        return [=]() 
            std::cout << this->text << "\n";
        ;
    
;

int main() 
    A a;
    auto printer = a.printer();
    a.text = "Hello, world!";

    printer();

【讨论】:

this 是当前对象,是通过引用捕获的,不是吗? this 是指向当前对象的指针,通过引用捕获。捕获this 指针实际上是通过引用捕获对象。 是的,这就是为什么我发现您的说法“......已经通过价值捕捉到了这一点”具有误导性。 我不知道,因为this 是一个指针,这就是按值复制指针的工作原理。【参考方案4】:

[=] 将起作用,因为它通过复制捕获了 lambda 主体中使用的所有自动变量。

这是示例输出:https://www.ideone.com/kkXvJT

#include <iostream>
#include <functional>

class Foo

  int x, y, z;
  std::function<void(void)> _func;

public:
  Foo(int a): x(a), y(0), z(0)  

  void bar()
  
    int a = 1,b,c;
    _func = [=]()
    
      int u = this->x + a;
      std::cout << u << std::endl;
    ;

    _func(); // lambda call
  
;

int main()

  Foo obj(1);
  obj.bar();

【讨论】:

以上是关于C ++ 11 lambda捕获`this`并按值捕获局部变量的主要内容,如果未能解决你的问题,请参考以下文章

在 C++11 中按值或引用使用 lambda 默认捕获的缺点?

C ++ 0x lambda按值捕获总是const?

在 lambda 中,引用的按值捕获是不是会复制底层对象?

Lambda 按值捕获和“可变”关键字

在c ++ 11中按值捕获成员变量的好方法是啥? [复制]

第18课 捕获机制及陷阱