C++ lambda捕获此对比通过引用捕获

vik*_*.rk 15 c++ lambda c++11 std-function

如果我需要生成一个调用成员函数的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
}
Run Code Online (Sandbox Code Playgroud)

Cra*_*ott 15

对于您提供的具体示例,捕获this是您想要的.从概念上讲,this通过引用捕获并不是很有意义,因为您无法更改其值this,您只能将其用作访问类成员或获取类实例地址的指针.在lambda函数内部,如果您访问隐式使用this指针的内容(例如,您调用成员函数或访问成员变量而不显式使用this),编译器会将其视为您仍然使用过this.您也可以列出多个捕获,因此如果要捕获成员和局部变量,可以单独选择是通过引用还是通过值捕获它们.以下文章应该为您提供lambdas和捕获的良好基础:

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

此外,您的示例std::function用作返回类型,lambda通过该类型传递回调用方.请注意,std::function并不总是像您想象的那么便宜,所以如果您能够直接使用lambda而不必将其包装在一个中std::function,那么它可能会更有效率.以下文章虽然与您的原始问题没有直接关系,但仍然可以为您提供一些与lambdas相关的有用资料std::function(请参阅存储函数对象的另一种方法,但文章一般可能会引起关注):

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


R S*_*ahu 6

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


Jer*_*fin 6

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

#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();
}
Run Code Online (Sandbox Code Playgroud)

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

Before thing1: local bar: 1, this->bar: 0
After thing1: local bar: 2, this->bar: 0
After thing2: local bar: 2, this->bar: 3
Run Code Online (Sandbox Code Playgroud)

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


sky*_*ack 5

是一个什么样的很好的解释&this并在捕获列表使用时,其他人表示。

在您的情况下,假设您要做的只是调用实例的成员函数,而该实例函数实际上由this当前正在执行的方法的引用,则将其放入this捕获列表中就足够了。

  • 如果您对某些东西的工作原理有一个粗略的了解并想要查找它,那么 cppreference 会很好。我非常不同意这对OP的问题有一个“好的”解释。至少不是“好”“初学者可以理解”的意义上的。 (9认同)