【问题标题】:Why can't a data member be in a lambda capture list为什么数据成员不能在 lambda 捕获列表中
【发布时间】:2014-05-22 09:43:01
【问题描述】:

我有一个类 foo,它有 bar 作为成员变量。

在该类的另一个成员函数中,我正在编写一个 lambda 函数:

[bar](void){}

但我不能在捕获列表中包含bar。这是为什么呢?

【问题讨论】:

  • 您确定与const的成员有关吗?
  • 其实,没有。它对所有成员都失败。我会修改问题。
  • 我为你改好了标题。
  • 糟糕。如果你在梅菲尔,那是我欠你的啤酒。

标签: c++ c++11 lambda


【解决方案1】:

只有具有自动存储持续时间的对象才能被 C++11 中的 lambda 捕获(即局部变量和函数参数)。如果您想要捕获non-static 类数据成员的效果,您可以捕获this 指针,如Danvil's answer

auto f = [this]{ std::cout << a << std::endl; };

或将数据成员的值缓存在局部变量中并捕获:

auto a = this->a;
auto f = [a]{ std::cout << a << std::endl; };

在 C++14 中会更加简洁:

auto f = [a = this->a]{ std::cout << a << std::endl; };

这两个选项之间的选择取决于您是要存储值a 具有现在,还是要检索值a 具有当 lambda 是称为。请注意,在捕获 this 的情况下,您必须确保指针对象的生命周期包含 lambda 的生命周期,在对象被销毁后对 lambda 的调用具有未定义的行为。捕获a 副本的更简单案例是完全独立的,没有此类生命周期问题。

【讨论】:

  • 但是使用[this] 和使用[a = this-&gt;a] 不一样——还是我弄错了?
  • @Danvil 正确。 [a = this-&gt;a] 捕获 this-&gt;a 的副本,但不需要像在本地缓存 this-&gt;a 的 2 行 C++11 版本那样的中间副本。
  • 自动 const& a = this->a;保存一份?
  • 如果您想通过引用进行捕获,auto f = [&amp;a = this-&gt;a]{ std::cout &lt;&lt; a &lt;&lt; std::endl; }; 也可以使用。
【解决方案2】:

您可以通过在捕获列表中说出this 来捕获班级成员。这与成员是const这一事实无关。


例子:

#include <iostream>

struct Foo
{
    const int a = 0;
    int b;
    Foo() : b{42} {
        auto f = [this]() { std::cout << a << " " << b << std::endl; };
//                ^^^^ 
        f();
    }
};

int main() {
    Foo x;
}

【讨论】:

  • 这是不正确的。如果在捕获列表中指定this,则捕获的是this 指针的值,而不是类成员的值。您所拥有的将在大部分时间编译和工作,但您所拥有的并不是线程安全的。 ab 的值可以在创建 lambda 之后但在计算之前更改。请参阅 Casey 的另一个答案以使其线程安全。
  • 是程序员的选择,是要副本还是参考。
  • 您是对的,但在原始问题中,OP 试图通过值而不是引用来捕获 bar。通过值捕获this 指针通过引用捕获成员变量。
猜你喜欢
  • 2014-03-24
  • 2011-12-15
  • 2015-11-12
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 2013-04-25
相关资源
最近更新 更多