С++ 11 lambda: смешанный список захвата

Может ли кто-нибудь, пожалуйста, показать мне следующие примеры:

1) Лямбда, которая фиксирует x по значению. y по ссылке. Что остальное по умолчанию, если не указано?

2) Лямбда, которая фиксирует x по значению. y по ссылке, все остальное по значению.

3) Лямбда, которая фиксирует x по значению. y по ссылке, все остальное по ссылке.

Кроме того, разрешено ли, что 2 лямбда в одном и том же объеме имеют одну и ту же подпись захвата, например, оба являются [] или оба являются [& x, =]

благодаря

Ответы

Ответ 1

1) [x, &y](){} остался не захвачен

2) [=, &y](){}

3) [&, x](){}

Список захвата представляет собой список с нулевым или большим количеством символов, разделенный запятыми, необязательно начинающийся с по умолчанию для захвата. Единственными значениями по умолчанию для захвата являются & (по ссылке) и = (по значению). Если используется захват по умолчанию, никакие другие записи не могут использовать один и тот же тип захвата. Любой захват может появляться только один раз.

Кроме того, разрешено ли, что 2 лямбда в одном и том же объеме имеют одну и ту же подпись захвата, например, оба являются [] или оба являются [& x, =]

Конечно, это разрешено. Каждая лямбда будет отдельным объектом и имеет свой особый тип. Если вы возьмете переменную по значению в два лямбда, то каждая лямбда будет иметь свою копию. Если вы возьмете переменную по ссылке в два лямбда, то каждая лямбда будет иметь ссылку на одну и ту же захваченную переменную.

Ответ 2

Можно просто написать несколько примеров:

int x = 7, y = 12, z = 24;

auto lambda1 = [x, &y]{
    // can't do this...
    // std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
    std::cout << "x=" << x << ", y=" << y << std::endl;
};

auto lambda2 = [=, x, &y]{
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};

auto lambda3 = [&, x, &y]{
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};

++x, ++y, ++z;
lambda1();
lambda2();
lambda3();

Теперь lambda1 здесь не может использовать z. Там нет "неявного" захвата, так как мы не имеем = или & указание и z не отображается в списке захвата, мы не можем напечатать z там. Так что ошибка, если мы попытаемся использовать эту строку, я прокомментировал.

Остальные два являются точными и будут печатать 7, 13, 24 и 7, 13, 25 соответственно. Обратите внимание, что the = и & должны быть первыми. Кроме того, учитывая, что мы захватываем все по значению/ссылке, один из других захватов является избыточным, поэтому мы могли бы сделать:

auto lambda2 = [=, &y]{ ... };
auto lambda3 = [&, x]{ ... };

Ответ 3

1)

[x,&y](){} // the rest is not captured, eg 'z' is not defined in the scope

2)

[=,&y](){} // '=' is capture everything by value

3)

[&,x](){} // '&' is capture everything by reference

Ответ 4

Чтобы процитировать Bjarne из его С++ 11 FAQ:

[&] - это "список захвата", указывающий, что используемые локальные имена будут передаваться по ссылке. Мы могли бы сказать, что мы хотели "захватить" только v, мы могли бы сказать так: [& v]. Если бы мы хотели передать v по значению, мы могли бы сказать так: [= v]. Захват ничего не равен [], захват всех по ссылкам [&], а захват по значению - [=]. Если действие не является обычным и простым, я рекомендую использовать именованный функциональный объект или функцию.