在以下函数中,我可以依赖捕获的变量'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
答案 0 :(得分:2)
你必须认识到的是lambda是一个闭包类型的对象:
lambda表达式是一个prvalue表达式,是一个未命名的唯一非联合非聚合类类型的临时对象,称为闭包类型,在最小块范围内声明(出于Argument-Dependent Lookup的目的),类范围或包含lambda表达式 [source]
的命名空间范围
您可以将lambda的捕获列表视为构造函数参数。在这种情况下,您通过值/引用将order
分别传递到1 st / 2 nd comparators
。 由于order
在comparators
的生命周期内没有变化,因此通过引用或值传递将在您的示例中得到相同的结果。
但是如果调用此函数并将order
设置为Ascending
,并将其添加到sortByColumn
的底部:
order = Descending;
std::sort(entries.begin(), entries.end(), comparators[0]);
您可以按{strong>降序顺序按entries
排序name
。意味着对order
的更改影响了lambda。
如果您已完成此操作,sortByColumn
再次成为order
Ascending
:
order = Descending;
std::sort(entries.begin(), entries.end(), comparators[1]);
您可以按{strong>升序顺序按entries
排序earnings
。意味着对order
的更改不会影响lambda。
在决定是否通过引用捕获时,应该应用相同的注意事项,用于决定是否将引用或副本用作对象成员:
答案 1 :(得分:2)
std::function<bool(const Entry&, const Entry&)> comparators[] =
{
[order](const Entry& a, const Entry& b) { return order==Ascending ? a.name < b.name : a.name > b.name; },
[order](const Entry& a, const Entry& b) { return order==Ascending ? a.earnings < b.earnings : a.earnings > b.earnings; }
};
sortByColumn
是可以重入的。除了更改entries
之外,它没有任何状态,也没有副作用。如果你关心性能,最好检查lambda之外的order
排序并将lambda直接传递给std::sort
,而不是将其放入std::function
。首先你需要四种不同的lambdas。