您应该通过引用捕获数据成员还是使用 lambda 中的 [this] 捕获数据成员?

问题描述 投票:0回答:4

如果我需要生成一个调用成员函数的 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
}
c++ c++11 lambda std-function
4个回答
37
投票

对于您提供的具体示例,通过

this
捕获就是您想要的。从概念上讲,通过引用捕获
this
没有多大意义,因为您无法更改
this
的值,只能将其用作访问类成员或获取地址的指针类实例的。在 lambda 函数内部,如果您访问隐式使用
this
指针的内容(例如,您在没有显式使用
this
的情况下调用成员函数或访问成员变量),编译器会将其视为您已经使用了
this
。您也可以列出多个捕获,因此如果您想同时捕获成员变量和局部变量,您可以独立选择是通过引用还是通过值捕获它们。以下文章将为您提供 lambda 和捕获的良好基础:

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

此外,您的示例使用

std::function
作为返回类型,通过该类型将 lambda 传递回调用者。请注意,
std::function
并不总是像您想象的那么便宜,因此如果您能够直接使用 lambda 而不必将其包装在
std::function
中,它可能会更有效。下面的文章虽然与您原来的问题没有直接关系,但仍然可能为您提供一些与 lambda 和
std::function
有关的有用材料(请参阅另一种存储函数对象的方法部分,但这篇文章总体上可能是兴趣):

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


10
投票

Here 很好地解释了

&
this
和其他在捕获列表中使用时表示的含义。

在您的情况下,假设您所要做的就是调用当前正在执行的方法的

this
实际引用的实例的成员函数,将
this
放入捕获列表中应该就足够了。


7
投票

捕获

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


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();
}

如您所见,捕获

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
所独有的。捕获任何指针都可以让您访问它所指向的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.