C++ lambda 捕获这个 vs 通过引用捕获

C++ lambda capture this vs capture by reference

如果我需要生成调用成员函数的lambda,我应该通过引用捕获还是捕获'this'?我的理解是'&'只捕获使用的变量,而'this'捕获所有成员变量。那么最好使用“&”?

class MyClass {
  public:
    int mFunc() {
      // accesses member variables
    }

    std::function<int()> get() {
      //return [this] () { return this->mFunc(); };
      //  or
      //return [&] () { return this->mFunc(); };
    }

  private:
    // member variables
}

捕获this和引用捕获是两个正交的概念。您可以使用一个、两个或 none。通过引用捕获 this 没有意义,但您可以在通过值捕获 this 的同时通过引用捕获其他变量。

Here 很好地解释了 &this 和其他在捕获列表中使用时所指示的内容。

在你的情况下,假设你所要做的就是调用实例的成员函数,该实例实际上被当前正在执行的方法的 this 引用,将 this在您的捕获列表中应该足够了。

对于您提供的具体示例,您希望通过 this 进行捕获。从概念上讲,通过引用捕获 this 没有多大意义,因为您无法更改 this 的值,您只能将其用作访问 [= 成员的指针32=] 或获取 class 实例的地址。在你的 lambda 函数中,如果你访问隐式使用 this 指针的东西(例如,你调用一个成员函数或访问一个成员变量而不显式使用 this),编译器将它视为你已经使用this 无论如何。你也可以列出多个捕获,所以如果你想同时捕获成员和局部变量,你可以独立地选择是通过引用还是通过值来捕获它们。以下文章应该让您在 lambda 和捕获方面有一个良好的基础:

https://crascit.com/2015/03/01/lambdas-for-lunch/

此外,您的示例使用 std::function 作为 return 类型,lambda 通过该类型传递回调用方。请注意,std::function 并不总是像您想象的那么便宜,因此如果您能够直接使用 lambda 而不是必须将其包装在 std::function 中,它可能会更有效率。以下文章虽然与您的原始问题没有直接关系,但可能仍会为您提供一些与 lambda 和 std::function 相关的有用 material(请参阅 存储函数对象的替代方法部分,但总的来说这篇文章可能会让人感兴趣):

https://crascit.com/2015/06/03/on-leaving-scope-part-2/

这不是一个明确的情况。相反,两者(至少可能)完成的事情略有不同。例如,考虑这样的代码:

#include <iostream>

    class foo { 
        int bar = 0;
    public:
        void baz() {
            int bar = 1;
            auto thing1 = [&] { bar = 2; };
            auto thing2 = [this] { this->bar = 3; };

            std::cout << "Before thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";    
            thing1();
            std::cout << "After thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";
            thing2();
            std::cout << "After thing2: local bar: " << bar << ", this->bar: " << this->bar << "\n";
        }
    };


int main() { 
    foo f;
    f.baz();
}

如您所见,捕获this仅捕获可以通过this引用的变量。在这种情况下,我们有一个局部变量来隐藏实例变量(是的,这通常是个坏主意,但在这种情况下,我们使用它来显示每个实例的部分功能)。正如我们在 运行 程序中看到的那样,捕获 this 与通过引用隐式捕获得到不同的结果:

Before thing1: local bar: 1, this->bar: 0
After thing1: local bar: 2, this->bar: 0
After thing2: local bar: 2, this->bar: 3

关于捕获所有内容与仅捕获您使用的内容的具体细节:两者都不会捕获您不使用的任何变量。但是,由于 this 是一个指针,捕获该变量可以让您访问它指向的所有内容。不过,这并不是 this 独有的。捕获任何指针将使您可以访问它指向的任何内容。