【问题标题】:C++ lambda capture this vs capture by referenceC++ lambda 捕获 this vs 通过引用捕获
【发布时间】:2016-02-08 02:49:39
【问题描述】:

如果我需要生成一个调用成员函数的 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


    【解决方案1】:

    对于您提供的具体示例,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 中,它可能会更有效。以下文章虽然与您的原始问题没有直接关系,但仍可能为您提供一些与 lambdas 和 std::function 相关的有用材料(请参阅存储函数对象的另一种方法部分,但文章一般情况下可能会感兴趣):

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

    【讨论】:

      【解决方案2】:

      Here 很好地解释了&amp;this 和其他在捕获列表中使用时的含义。

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

      【讨论】:

      • cppreference 如果您对某些东西的工作原理有一个粗略的了解并想查看它,那么它会很好。我非常不同意这对 OP 的问题有一个“好的”解释。至少在“好”的意义上不是“初学者可以理解的”。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        这不是一个明确的情况,即一个比另一个更好。相反,两者(至少可能)完成了稍微不同的事情。例如,考虑如下代码:

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

        【讨论】:

        • 除非您的本地 int bar = 1 声明,捕获 [&amp;] 和捕获 [this] 将完全等效,对吗? (他们都会通过引用捕获foo::bar).. 甚至为此捕获[=]
        猜你喜欢
        • 2017-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-28
        • 1970-01-01
        • 2018-01-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多