#include
#include
2 : #include
linclude
using namespace std;
template
void DisplayContents (const T& Input)
8 : {
for(auto iElement = Input.cbegin() // auto, cbegin и cend: C++11
1 0 :
|
; iElement != Input.cend ()
|
1 1 :
|
; ++
|
iElement
|
)
|
1 2 :
|
cout «
|
*iElement
|
« endl;
|
}
int main ()
{
// Определить вектор строк для содержания и^аен
vector vecNames;
19:
2 0 : // Вставить в вектор несколько примеров имен
vecNames.push_back ("jim"); vecNames.push_back ("Jack");
vecNames.push_back ("Sam");
vecNames.push_back ("Anna");
cout « "The names in vector in order of insertion: " « endl;
DisplayContents(vecNames);
28:
|
cout « "Names after sorting using default std::less<>: "
|
29:
|
endl;
sort(vecNames.begin(), vecNames.end());
DisplayContents(vecNames);
32:
33: cout « "Names after sorting using predicate that ignores case:"
endl;
sort(vecNames.begin(), vecNames.end(),
[](const strings strl, const strings str2) -> bool
лямбда
{
44:
45:
46:
47:
48:
string strlLowerCase;
Зарезервировать пространство strlLowerCase.resize (strl.size ());
Преобразовать каждый символ в нижний регистр transform(strl.begin(), strl.end(),
strlLowerCase.begin(), tolower);
string str2LowerCase; str2LowerCase.resize (str2.size ()); transform (str2.begin (), str2.end (),
str2LowerCase.begin (),
tolower);
510 ЗАНЯТИЕ 22. Лямбда-выражения языка С++11
49:
return (strlLowerCase < str2LowerCase);
} // конец лямбды
); // конец сортировки
DisplayContents(vecNames);
54:
return 0;
}
Результат
The names in vector in order of insertion:
jim
Jack
Sam
Anna
Names after sorting using default std::less<>:
Anna
Jack
Sam
jim
Names after sorting using predicate that ignores case:
Anna
Jack
jim
Sam
Анализ
Здесь приведена большая лямбда-функция, охватывающая строки 35-51, как третий параметр алгоритма s t d : : s o r t (), который начинается в строке 34 и заканчивается в строке 52! Это показывает, что лямбда-функция может состоять из нескольких операторов и предваряться явным определением типа возвращаемого значения (b o o l), как показано
строке 35. Вывод демонстрирует содержимое вектора после вставки значений, где j im следует перед Ja c k , содержимое вектора после сортировки по умолчанию без предостав ленных лямбды и предиката (строка 30), где j im следует после Sam благодаря чувстви
тельному к регистру оператору s t r i n g : : o p e r a t o r ^ и наконец, версию, использующую
независящее от регистра лямбда-выражение (строки 34-52), где j im следует после Ja c k ,
как и ожидал бы обычно пользователь. Кроме того, при этой сортировке используется лямбда-выражение, охватывающее несколько строк.
ПРИМЕЧАНИЕ
|
Необычно большое лямбда-выражение листинга 22.5 является лямбда-версией
|
|
|
|
|
класса CompareStringNoCase из листинга 21.6, используемого в листин
|
|
|
ге 21.7.
|
|
|
Безусловно, это не оптимальное использование лямбды, поскольку в данном
|
|
|
случае объект функции допускает повторное использование в нескольких вы
|
|
|
ражениях std::sort (), если нужно, а также в других алгоритмах, которые
|
|
|
нуждаются в бинарном предикате.
|
|
|
Поэтому лямбды необходимо использовать тогда, когда они коротки, изящны и
|
|
|
эффективны.
|
|
|
|
|
|
|
|
|
|
|
Резюме
|
5 1 1
|
|
РЕКОМЕНДУЕТСЯ
|
|
|
НЕ РЕКОМЕНДУЕТСЯ
|
|
|
Помните, что лямбда-выражения всегда на
|
Не забывайте,
|
что лямбда-выражения -
|
это
|
|
чинаются с квадратных скобок ([]) или
|
безымянные представления класса или струк
|
|
([statel,
|
state2*,.])
|
|
туры с оператором operator ()
|
|
|
Помните, что если не указано иное, перемен
|
Не забывайте использовать константные па
|
|
ные состояния, предоставляемые в пределах
|
раметры при создании лямбда-выражений
|
|
списка захвата [],
|
не допускают изменения.
|
[] (const
|
Т&
|
value) { II лямбда-
|
|
Для возможности изменения используйте клю
|
выражение
|
;
|
}
|
|
|
чевое слово mutable
|
|
|
Не забывайте явно указывать тип возвра
|
|
|
|
|
|
|
|
щаемого значения, когда лямбда-выражение
|
|
|
|
|
|
|
|
включает несколько операторов в пределах
|
|
'
|
.......
|
|
'
|
<: "
|
.". й.. ''
|
блока {)
|
|
|
|
|
: .•:! ' •
|
|
|
|
Не предпочитайте лямбда-выражения объекту
|
|
: '
|
, •
|
' ■
|
■
|
|
|
|
|
|
функции, когда лямбда становится чрезвычайно
|
длинной и охватывает несколько операторов,
поскольку они переопределяются при каждом
использовании и не позволяют использовать
код повторно
Резюме
На сегодняшнем занятии рассматривалось очень важное средство языка C++11 — лямбда-функции. Вы узнали, что лямбды — это безымянные объекты функций, способные получать параметры, хранить состояние, возвращать значения и быть многострочными. Вы научились использовать лямбды вместо объектов функций в таких алгоритмах STL, как fin d (), s o r t () или tra n sfo rm (). Лямбды делают программирование на C++ бы стрым и эффективным, поэтому постарайтесь использовать их по возможности чаще.
Вопросы и ответы
Всегда ли я должен предпочитать лямбды объектам функций?
Лямбды, охватывающие несколько строк (листинг 22.5), не помогут увеличить эффек тивность программы по сравнению с объектом функции, который легко можно исполь зовать многократно.
К ак передаются парам етры состояния лямбды, по значению или по ссылке?
Лямбда создается со списком захвата так:
[Varl, Var2, ... N](Туре& Paraml, ... ) { ...expression ;}
Параметры состояния V a r l и Var2 копируются (а не передаются по ссылке). Если хо тите иметь их как ссылочные параметры, используйте такой синтаксис:
[&Varl, &Vаг2, ... &N](Туре& Paraml, ... ) { ...expression ;}
В данном случае нужна осторожность, поскольку модификация переменных состояния, переданных в пределах списка захвата, распространяется вне лямбды.
Могу ли я использовать локальны е переменные в лямбде как в функции?
512 ЗАНЯТИЕ 22. Лямбда-выражения языка С++11
Вы можете передать локальные переменные в списке захвата:
Do'stlaringiz bilan baham: |