【问题标题】:Temporary captured-variables in lambda functions - C++11lambda 函数中的临时捕获变量 - C++11
【发布时间】:2021-02-07 23:51:07
【问题描述】:

我正在尝试这样的方法来使用字符串向量列表预填充地图。 代码不言自明:

Constructor(const vector<string>& names) {
  for_each(names.begin(), names.end(),
                     [this, counter = 1](const String& choice) mutable {
                            nameMapping.emplace(choice, counter++);
                        }
  );
}

我不太明白counter 是如何工作的?

仅供参考:counter 没有在 lambda 函数之外声明。

但是,我能够在类范围内创建一个局部变量并在可变 lambda fn 中对其进行修改?

有人可以帮我理解发生了什么。

【问题讨论】:

  • 发生了什么,基本上,lambda 捕获是如何工作的。捕获的变量的类型是从初始化它的表达式的类型推断出来的。除了这就是 C++ lambda 的工作方式之外,这里真的没什么好说的了。
  • 好像你可以写auto counter = 1

标签: c++ c++11 lambda


【解决方案1】:

当您设置counter = 1 时,您将声明一个新的临时counter 等于1。编译器负责确定类型。这个临时对象默认推导出为int 类型,并在 lambda 存在时存在。

通过设置mutable,你可以同时修改counterthis

除此之外:由于您似乎正在插入地图/无序地图,因此您最好使用以下方法:

#include <algorithm> // For transform
#include <iterator>  // For inserter

Constructor(const vector<string>& names) {
    auto const example = [counter = 1](const string& item) mutable {
        return {item, counter++};
    };
    std::transform(names.begin(), names.end(),
                   std::inserter(nameMapping, nameMapping.end()), example);
}

通过将 nameMapping 调用移到 lambda 之外,您不必混淆范围内的内容和不在范围内的内容。

此外,您可以避免不必要的捕获,以及任何其他可能让您自己或其他读者在未来感到困惑的事情。

【讨论】:

  • “这个临时对象默认被推断为 int 类型” 此处“默认”一词的使用可能会造成混淆;它只是一个int,因为文字1 是一个int
  • 无论如何您都不需要任何这种复杂性。一个 lambda,一个捕获,mutablestd::transformstd::inserter,两个标头...为什么?!您只需要声明一个int,然后编写一个两行的for 循环。这真的很简单。
【解决方案2】:

但是,我能够在类范围内创建一个局部变量并在可变 lambda fn 中对其进行修改?

有人可以帮我理解发生了什么。

正如你所说。

可能会造成混淆,因为在这种特定类型的声明中没有给出类型。就我个人而言,我认为这是一个糟糕的设计决定,但我们去吧。

想象一下它改为auto counter = 1auto 已为您完成。然后该变量成为 lambda 对象的“成员”,赋予它状态。

代码不是很好,因为不能保证 lambda 按顺序应用于容器元素。一个简单的for 循环可以说会更简单、更清晰和可预测:

Constructor(const vector<string>& names)
{
   int counter = 1;
   for (const string& name : names)
      nameMapping.emplace(name, counter++);
}

真的没有理由仅仅为了使用“花哨”的标准算法而使事情复杂化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    相关资源
    最近更新 更多