c++ - 什么时候初始化 lambda 捕获?

标签 c++ lambda

在下面的函数中,我可以依赖捕获的变量'order'是最新的吗,即

  1. 该功能是否始终按预期运行?
  2. 按值或引用捕获之间有区别吗。
  3. 函数是否可重入?
struct Entry
{
    std::string name;
    double earnings;
};

enum Column { Name, Earnings };
enum SortOrder { Ascending, Descending };

void sortByColumn(std::vector<Entry>& entries, Column column, SortOrder order)
{
    std::function<bool(const Entry&, const Entry&)> comparators[] =
    {
        [&](const Entry& a, const Entry& b) { return order==Ascending ?
            a.name < b.name : a.name > b.name;  },
        [=](const Entry& a, const Entry& b) { return order==Ascending ?
            a.earnings < b.earnings : a.earnings > b.earnings;  }
    };
    std::sort(entries.begin(), entries.end(), comparators[column]);
}

您可以在此处找到完整示例:http://coliru.stacked-crooked.com/a/240b74d1706a1b6f

最佳答案

你必须认识到的是,lambda 是一个闭包类型的对象:

The lambda expression is a prvalue expression an unnamed temporary object of unique unnamed non-union non-aggregate class type, known as closure type, which is declared (for the purposes of Argument-Dependent Lookup) in the smallest block scope, class scope, or namespace scope that contains the lambda expression[source]

您可以将 lambda 的捕获列表视为构造函数参数。在这种情况下,您通过值/引用将 order 分别传递给 1st/2nd comparators由于 ordercomparators 的生命周期内不会改变,因此在您的示例中通过引用或值传递将产生相同的结果。

但是如果调用此函数时 order 设置为 Ascending 并且您将其添加到 sortByColumn 的底部:

order = Descending;
std::sort(entries.begin(), entries.end(), comparators[0]);

您可以按名称降序 顺序对条目 进行排序。这意味着对 order 的更改影响了 lambda。

但是,如果您这样做了,并且 sortByColumn 再次以 order 作为 Ascending 传递:

order = Descending;
std::sort(entries.begin(), entries.end(), comparators[1]);

您可以按收入升序 顺序对条目 进行排序。这意味着对 order 的更改不会影响 lambda。


在决定是否通过引用捕获时,应该应用与决定是否使用引用或拷贝作为对象成员时相同的考虑因素:

  1. 如果无法复制构造对象,则必须使用引用,如果复制构造成本高昂,则可以选择使用引用
  2. 如果 lambda 的生命周期将超过它捕获的生命周期,您必须制作一个拷贝,并且如果您提供要使用的 lambda 表达式,您可以选择使用制作拷贝在你的代码之外

关于c++ - 什么时候初始化 lambda 捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38768396/

相关文章:

Android/C++数据序列化

c++ - 在着色器中同时在同一纹理单元中使用不同的纹理类型

c++ - Pimpl 习语和没有友元声明的内部对象协作

c# - 使用 C++/CLI 将对象从 C# 传递到 C++ 或将 Object^ 转换为 Object

python - 使用 lambda 提高迭代数据帧时的代码效率

java - 仅使用流收集结果(不使用外部循环)

python django 使用 lambda 和 if 语句进行排序

c++ - 将 C++ 成员函数指针传递给 STL 算法

java - 原始数组上的 Lambda

java - 如何在 Java 流中舍入平均值?