在下面的函数中,我可以依赖捕获的变量'order'是最新的吗,即
- 该功能是否始终按预期运行?
- 按值或引用捕获之间有区别吗。
- 函数是否可重入?
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
。 由于 order
在 comparators
的生命周期内不会改变,因此在您的示例中通过引用或值传递将产生相同的结果。
但是如果调用此函数时 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。
在决定是否通过引用捕获时,应该应用与决定是否使用引用或拷贝作为对象成员时相同的考虑因素:
- 如果无法复制构造对象,则必须使用引用,如果复制构造成本高昂,则可以选择使用引用
- 如果 lambda 的生命周期将超过它捕获的生命周期,您必须制作一个拷贝,并且如果您提供要使用的 lambda 表达式,您可以选择使用制作拷贝在你的代码之外
关于c++ - 什么时候初始化 lambda 捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38768396/