Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Лямбда-выражения






Лямбда-выражение – это механизм определения объекта-функции. Основная цель лямбда-выражения заключается в определении некоторого действия, выполняемого некоторой функцией. Например:

vector< int> v = {50, -10, 20, -30};

// сортировка по умолчанию

std:: sort(v.begin(), v.end());

// теперь v должен содержать { -30, -10, 20, 50 }

// сортируем по абсолютному значению:

std:: sort(v.begin(), v.end(), [](int a, int b) { return abs(a)< abs(b); });

// теперь v должен содержать { -10, 20, -30, 50 }

 

Аргумент [](int a, int b) {return abs(a)< abs(b); } – это «лямбда» («лямбда-выражение» или «лямбда-функция»), определяющая операцию, которая для двух целочисленных аргументов a и b возвращает результат сравнения их абсолютных значений.

Лямбда-выражение может получить доступ к локальным переменным из области видимости, в которой оно используется. Например:

void f(vector< Record> & v)

{

vector< int> indices(v.size());

int count = 0;

generate(indices.begin(), indices.end(), [& count](){ return ++count; });

// сортируеминдексы в порядке, определяемым полем name записей:

std:: sort(indices.begin(), indices.end(),

[& ](int a, int b) { return v[a].name< v[b].name; });

//...

}

 

Некоторые считают эту возможность «очень классной!»; другие рассматривают ее как источник пугающе непонятного кода. ИМО, верны обе точки зрения.

[& ] представляет собой «список захвата» (“capture list”), который указывает, что локальные переменные передаются в лямбда-выражение по ссылке. Мы можем явно указать, что «захватываем» по ссылке только переменную v: [& v], или захватываем ее по значению: [=v]. [] означает, что ничего не захватывается, [& ] – означает захват всех переменных по ссылке, а [=] – захват всех переменных по значению.

Если действие не является простым или распространенным, то я рекомендую использовать именованный функциональный объект или функцию. Например, приведенный выше пример может быть переписан таким образом:

void f(vector< Record> & v)

{

vector< int> indices(v.size());

int count = 0;

fill(indices.begin(), indices.end(), [& ](){ return ++count; });

struct Cmp_names {

const vector< Record> & vr;

Cmp_names(const vector< Record> & r): vr(r) { }

bool operator()(Record& a, Record& b) const {

return vr[a]< vr[b];

}

};

// сортируеминдексы в порядке, определяемым полем name записей:

std:: sort(indices.begin(), indices.end(), Cmp_names(v));

//...

}

 

Для таких небольших функций, как функция сравнения записей по имени, использование функциональных объектов может быть слишком многословным, хотя сгенерированный код для обоих случаев будет скорее всего идентичным. В С++98 такие функциональные объекты должны быть нелокальными, однако в С++11 это уже не обязательно.

Для определения лямбда-выражения, вы должны указать:

· список захвата: список переменных, которые могут использоваться внутри лямбда-выражения (помимо аргументов), ([& ] означает «все локальные переменные передаются по ссылке», как в нашем примере с типом Record). Если лямбда-выражение не использует никакие захваченные переменные, то оно должно начинаться с [].

· (необязательно) аргументы с указанием их типов (например, (int a, int b)).

· Блок кода, представляющий некоторое действие (например, { return v[a].name< v[b].name; }).

· (необязательно) тип возвращаемого значения с помощью нового суффиксного стиля указания типов возвращаемого значения; но обычно мы можем вывести тип возвращаемого значения по возвращаемому выражению. Если возвращаемое значение отсутствует, то выводится тип void.

См. также:

  • Standard 5.1.2 Lambda expressions
  • [N1968=06-0038] Jeremiah Willcock, Jaakko Jarvi, Doug Gregor, Bjarne Stroustrup, and Andrew Lumsdaine: Lambda expressions and closures for C++ (original proposal with a different syntax)
  • [N2550=08-0060] Jaakko Jarvi, John Freeman, and Lawrence Crowl: Lambda Expressions and Closures: Wording for Monomorphic Lambdas (Revision 4) (final proposal).
  • [N2859=09-0049] Daveed Vandevoorde: New wording for C++0x Lambdas.

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.