简体   繁体   English

C++11 lambda:我们什么时候需要捕获 [*this] 而不是 [this]?

[英]C++11 lambda: when do we need to capture [*this] instead of [this]?

For a quick sample we could see:对于一个快速示例,我们可以看到:

class Foo {
  std::string s_; 
  int i_;
public:
  Foo(const std::string& s, int i) : s_(s), i_(i) {}
  void Print() {
    auto do_print = [this](){
      std::cout << s_ << std::endl;
      std::cout << i_ << std::endl;
    };
    do_print();
  }
};

Ok, capture [this], so the lambda do_print could use s_ and i_ member of Foo .好的,捕获 [this],因此 lambda do_print可以使用Foos_i_成员。 Capture [this] is enough.捕获[this]就足够了。

But when do we have to capture [*this] instand of [this]?但是我们什么时候必须捕获 [*this] 来代替 [this]? What could be a typical use-case / scenario, any quick samples?什么可能是典型的用例/场景,任何快速示例?

Thanks谢谢

You capture *this if you want a copy of the element to be captured.如果要捕获元素的副本,则捕获*this This can be useful if the element may change or go out of scope after the lambda is created, but you want an element that is as it was at the time of creating the lambda. This can be useful if the element may change or go out of scope after the lambda is created, but you want an element that is as it was at the time of creating the lambda.

#include <iostream>

class Foo {
    std::string s_;
    int i_;

public:
    Foo(const std::string& s, int i) : s_(s), i_(i) {}
    auto get_print() {
        return [*this] {                    // copy
            std::cout << s_ << std::endl;
            std::cout << i_ << std::endl;
        };
    }
};

auto func() {
    Foo foo("foo", 123);
    return foo.get_print();
} // foo goes out of scope

int main() {
    func()(); // but the lambda holds a copy, so this is ok, otherwise, UB
}

Also note that capturing *this requires C++17.另请注意,捕获*this需要 C++17。 A similar program in C++11 could look like this: C++11 中的类似程序可能如下所示:

#include <functional>
#include <iostream>

class Foo {
    std::string s_;
    int i_;

public:
    Foo(const std::string& s, int i) : s_(s), i_(i) {}

    std::function<void()> get_print() {
        auto Self = *this;
        return [Self] {
            std::cout << Self.s_ << std::endl;
            std::cout << Self.i_ << std::endl;
        };
    }
};

std::function<void()> func() {
    Foo foo("foo", 123);
    return foo.get_print();
}

int main() {
    func()();
}

The general rule with lambdas is that if the lambda doesn't escape the current scope (including copies), you can capture with [this] or [&] safely. lambdas 的一般规则是,如果 lambda 没有逃脱当前的 scope(包括副本),您可以使用[this][&]安全地捕获。

If it does escape the current scope, you should default to [=] and [*this] (well, and also naming things for [=] ).如果它确实逃脱了当前的 scope,你应该默认为[=][*this] (好吧,也为[=]命名)。 You should only capture by reference when the lambda escapes the current scope if you are willing to personally guarantee the lifetime of everything capture now and forever in the future, whenever the code is modified by a university intern just before they go back to school for their first course on C++ programming.仅当 lambda 转义当前 scope 时,如果您愿意亲自保证现在和将来捕获的所有内容的生命周期,则仅应通过引用捕获C++ 编程的第一门课程。

Lifetime management is hard .终身管理很难 You should avoid doing it and just capture things by value whenever you can.你应该避免这样做,只要有可能就按价值捕捉事物。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM