Скопируйте elision для захваченных локальных переменных в возвращаемой лямбде - PullRequest
2 голосов
/ 25 марта 2020

Возможна ли (или гарантированная) конструкция копирования (перемещения) в захвате по значению ([x]) (или захвате перемещения в C ++ 14 [x = std::move(x)]) в лямбда-выражении (в качестве возвращаемого значения) elised?

auto param_by_value(Widget w) {
    // manipulating w ...
    return [w] { w.doSomeThing(); };
}
auto param_by_move(Widget w) {
    // manipulating w ...
    return [w = std::move(w)] { w.doSomeThing() };
}
auto local_by_value() {
    Widget w;
    // manipulating w ...
    return [w] { w.doSomeThing(); };
}
auto local_by_move() {
    Widget w;
    // manipulating w ...
    return [w = std::move(w)] { w.doSomeThing() };
}

Мои вопросы:

  1. Возможно ли (или даже гарантировано) копирование (перемещение) для w в вышеуказанных функциях? (Я помню, что явное std::move иногда препятствовало бы исключению копирования, а копирование / перемещение для параметров невозможно исключить.)
  2. Если исключение копирования не произойдет в случаях 1 и 3, будет ли захват по значению для w вызовите конструктор перемещения из Widget?
  3. Что, по значению или с использованием std::move, должно быть предпочтительным в качестве наилучшей практики?

1 Ответ

4 голосов
/ 25 марта 2020

Лямбда-захваты по сути являются переменными-членами лямбда-объекта. Как таковые, они не подлежат какой-либо форме исключения, ни в их инициализации, ни в их использовании при перегрузке operator() лямбды.

И поскольку вызовы конструктора / деструктора являются наблюдаемым поведением, компилятор не допускается не вызывать их в соответствии с правилом «как будто» (если только компилятор не увидит код для этих конструкторов / деструкторов и не сможет доказать, что у них нет видимых побочных эффектов. Он также должен будет следовать по пути этой лямбды ваша кодовая база, между прочим. Так что, в принципе, не рассчитывайте на это).

При этом возвращение самой лямбды в соответствии с правилами C ++ 17 не будет вызывать копирование / перемещение лямбды и, следовательно, никаких дополнительных копий / перемещений членов этой лямбды не потребуется.

будет ли захват по значению для w вызывать конструктор перемещения Widget?

Нет. Поименные значения всегда копируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...