Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - [158]
>->), а за ней указать тип. Если лямбда-функция не имеет параметров, то список параметров (пустой) все равно необходим, иначе задать тип возвращаемого значения невозможно. Таким образом, предикат, проверяемый условной переменной, можно записать так:>cond.wait(lk, []()->bool{ return data_ready; });
Лямбда-функции с явно заданным типом возвращаемого значения можно использовать, например, для записи сообщений в журнал или для более сложной обработки:
>cond.wait(lk, []()->bool {
> if (data_ready) {
> std::cout << "Данные готовы" << std::endl;
> return true;
> } else {
> std::cout <<
> "Данные не готовы, продолжаю ждать" << std::endl;
> return false;
> }
>});
Даже такие простые лямбда-функции весьма полезны и существенно упрощают код, но их истинная мощь проявляется, когда требуется запомнить локальные переменные.
A.5.1. Лямбда-функции, ссылающиеся на локальные переменные
Лямбда-функции с лямбда-интродуктором вида >[] не могут ссылаться на локальные переменные из объемлющей области видимости; им разрешено использовать только глобальные переменные и то, что передано в параметрах. Чтобы получить доступ к локальной переменной, ее нужно захватить (capture). Проще всего захватить все переменные в локальной области видимости, указав лямбда-интродуктор вида >[=]. Теперь лямбда-функция может получить доступ к копиям локальных переменных на тот момент, когда эта функция была создана.
Рассмотрим этот механизм на примере следующей простой функции:
>std::function
> return [=](int j){return offset+j;};
>}
При каждом вызове >make_offseter с помощью обертки >std::function<> создается новый содержащий лямбда-функцию объект. Возвращенная функция добавляет указанное смещение к любому переданному ей параметру. Например, следующая программа
>int main() {
> std::function
> std::function
> std::cout <<
> offset_42(12) << "," << offset_123(12) << std::endl;
> std::cout <<
> offset_42(12) << "," << offset_123(12) << std::endl;
>}
два раза выведет числа >54, 135, потому что функция, возвращенная после первого обращения к >make_offseter, всегда добавляет 42 к переданному ей аргументу Напротив, функция, возвращенная после второго обращения к >make_offseter, добавляет к своему аргументу 123. Это самый безопасный вид захвата локальных переменных — все значения копируются, поэтому лямбда-функцию можно вернуть и вызывать вне контекста функции, в которой она была создана. Но это не единственно возможное решение, можно захватывать локальные переменные и по ссылке. В таком случае попытка вызвать лямбда-функцию после того, как переменные, на которые указывают ссылки, были уничтожены в результате выхода из области видимости объемлющей их функции или блока, приведёт к неопределённому поведению, точно так же, как обращение к уничтоженной переменной в любом другом случае.
Лямбда-функция, захватывающая все локальные переменные по ссылке, начинается интродуктором >[&]:
>int main() {
> int offset = 42; ←(1)
> std::function
> [&](int j){return offset + j;};←(2)
> offset = 123; ←(3)
> std::function
> [&](int j){return offset + j;};←(4)
> std::cout <<
> offset_a(12) << "," << offset_b(12) << std::endl; ←(5)
> offset = 99; ←(6)
> std::cout <<
> offset_a(12) << "," << offset_b(12) << std::endl; ←(7)
>}
Если функция >make_offseter из предыдущего примера захватывала копию смещения >offset, то функция >offset_a в этом примере, начинающаяся интродуктором >[&], захватывает >offset по ссылке (2). Неважно, что начальное значение >offset было равно 42 (1); результат вызова >offset_a(12) зависит от текущего значения >offset. Значение >offset было изменено на 123 (3) перед порождением второй (идентичной) лямбда-функции >offset_b(4), но эта вторая функция снова производит захват по ссылке, поэтому результат, как и прежде, зависит от текущего значения >offset.
Теперь при печати первой строки (5), >offset всё еще равно 123, поэтому печатаются числа >133, 135. Однако к моменту печати второй строки (7)>offset стало равно 99 (6), поэтому печатается >111, 111. И >offset_a, и >offset_b прибавляют текущее значение >offset (99) к переданному аргументу (12).
Но ведь это С++, поэтому вам не обязательно выбирать между всем или ничем; вполне можно захватывать одни переменные по значению, а другие по ссылке. Более того, можно даже указывать, какие именно переменные захватить. Нужно лишь изменить лямбда-интродуктор. Если требуется скопировать все видимые переменные, кроме одной-двух, то воспользуйтесь интродуктором >[=], но после знака равенства перечислите переменные, захватываемые по ссылке, предпослав им знаки амперсанда. В следующем примере печатается >1239, потому что переменная >i копируется в лямбда-функцию, a >j и >k захватываются по ссылке:
>int main() {
> int i=1234, j=5678, k=9;
> std::function
Это знаменитый бестселлер, который научит вас использовать власть массового сотрудничества и покажет, как применять викиномику в вашем бизнесе. Переведенная более чем на двадцать языков и неоднократно номинированная на звание лучшей бизнес-книги, "Викиномика" стала обязательным чтением для деловых людей во всем мире. Она разъясняет, как массовое сотрудничество происходит не только на сайтах Wikipedia и YouTube, но и в традиционных компаниях, использующих технологии для того, чтобы вдохнуть новую жизнь в свои предприятия.Дон Тапскотт и Энтони Уильямс раскрывают принципы викиномики и рассказывают потрясающие истории о том, как массы людей (как за деньги, так и добровольно) создают новости, изучают геном человека, создают ремиксы любимой музыки, находят лекарства от болезней, редактируют школьные учебники, изобретают новую косметику, пишут программное обеспечение и даже строят мотоциклы.Знания, ресурсы и вычислительные способности миллиардов людей самоорганизуются и превращаются в новую значительную коллективную силу, действующую согласованно и управляемую с помощью блогов, вики, чатов, сетей равноправных партнеров и личные трансляции.
Автор книги — американский специалист по программированию, один из руководителей фирмы IBM, в своей книге делает попытку изложить общие проблемы создания программного обеспечения, его сопровождения и использования. Особенно подробно рассматриваются все фазы разработки программ разных типов. Изложение ясное, удачно иллюстрировано примерами.Для программистов разной квалификации и пользователей ЭВМ.fb2: ВНИМАНИЕ. В тексте присутствуют таблицы. Рекомендуется читать файл с помощью программы, поддерживающей их отображение.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.