Лямбды в С++ - это просто синтаксический сахар для функторов (функциональных объектов, объектов с перегруженным operator() (оператор "круглые скобки")). Стало быть применять их можно там же, где и функторы. А функторы - там же, где и указатели на функции. Это все об одном и том же примерно.
1) Первое преимущество функциональных объектов (и лямбд) в том, что у них есть состояние (хотя чистые функциональные языки считают изменяемое состояние недостатком, но у них вообще другая парадигма, другие проблемы и другие решения для них).
Например:
Код
auto getCounter = [](int initialValue) {
return [initialValue]() mutable {
return initialValue--;
};
};
auto c = getCounter(5);
while (c()) {
std::cout << "Hello lambda" << std::endl;
}
Это эквивалентно созданию функтора:
Код
class Counter {
int m_state;
public:
Counter(int initialValue) : m_state(initialValue) {}
int operator()() {
return m_state--;
}
};
Counter getCounter(int initialValue) {
return Counter(initialValue);
}
Counter c = getCounter(5);
while (c()) {
std::cout << "Hello lambda" << std::endl;
}
2) Лямбды анонимны и не засоряют пространство имен. Если нужно куда-то передать функцию/функтор, иногда нет смысла давать ей имя, если она всего один раз используется.
Тут уже приводили пример:
Цитата Saitei (
)
std::sort(v.begin(), v.end(), [](auto a, auto b) { return abs(a)<abs(b); });
3) Лямбды можно куда-то передавать, добавлять в какие-то контейнеры, передавать обработчикам, которые будут выполнять их в другом потоке. Например, есть какой-то обработчик SQL-запросов, куда из разных потоков отправляются запросы, а он их выполняет последовательно, предотвращая коллизии.
4) Лямбды могут синтаксически замыкать контекст. Например можно взять по ссылке переменную из окружения двух лямбд и использовать ее как разделяемую память. А сами лямбды передать обработчику для асинхронного выполнения. Тогда следующая лямбда может понять, выполнилась ли первая и использовать ее результат.
Код
int result = 0;
sequencer->addTask( [&result, this]() {
result = doSomething();
});
sequencer->addTask( [&result, this]() {
if (result) {
// everything is ok, we can process result
}
});