Читаем Параллельное программирование на С++ в действии полностью

два раза выведет числа 54, 135, потому что функция, возвращенная после первого обращения к make_offseter, всегда добавляет 42 к переданному ей аргументу Напротив, функция, возвращенная после второго обращения к make_offseter, добавляет к своему аргументу 123. Это самый безопасный вид захвата локальных переменных — все значения копируются, поэтому лямбда-функцию можно вернуть и вызывать вне контекста функции, в которой она была создана. Но это не единственно возможное решение, можно захватывать локальные переменные и по ссылке. В таком случае попытка вызвать лямбда-функцию после того, как переменные, на которые указывают ссылки, были уничтожены в результате выхода из области видимости объемлющей их функции или блока, приведёт к неопределённому поведению, точно так же, как обращение к уничтоженной переменной в любом другом случае.

Лямбда-функция, захватывающая все локальные переменные по ссылке, начинается интродуктором [&]:

int main() {

 int offset = 42;                ←(1)

 std::function offset_a =

  [&](int j){return offset + j;};←(2)

 offset = 123;                   ←(3)

 std::function offset_b =

  [&](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 f=[=,&j,&k] {return i+j+k;};

 i = 1;

 j = 2;

 k = 3;

 std::cout << f() << std::endl;

}

Можно поступить и наоборот — по умолчанию захватывать по ссылке, но некоторое подмножество переменных копировать. В таком случае воспользуйтесь интродуктором [&], а после знака амперсанда перечислите переменные, захватываемые по значению. В следующем примере печатается 5688, потому что i захватывается по ссылке, a j и k копируются:

int main() {

 int i=1234, j=5678, k= 9;

 std::function f=[&,j,k] {return i+j+k;};

 i = 1;

 j = 2;

 k = 3;

 std::cout << f() << std::endl;

}

Если требуется захватить только именованные переменные, то можно опустить знак = или & и просто перечислить захватываемые переменные, предпослав знак амперсанда тем, что должны захватываться по ссылке, а не по значению. В следующем примере печатается 5682, потому что i и k захвачены по ссылке, a j скопирована

int main() {

 int i=1234, j=5678, k=9;

 std::function f=[&i, j, &k] {return i+j+k;};

 i =1;

 j = 2;

 k = 3;

 std::cout << f() << std::endl;

}

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных