C ++ 0x: захват по значению для лямбды, всегда копия? - PullRequest
14 голосов
/ 12 марта 2011

Разрешено ли компилятору исключить копию , которая требуется для захвата по значению ?

vector<Image> movie1;
apply( [=movie1](){ return movie1.size(); } );
  • Есть ли какие-либо обстоятельства, которыекомпилятору не нужно копировать movie1?
    • Может быть, если бы компилятор мог знать, что apply на самом деле не меняет movie1?
    • Или это помогает, что лямбды по умолчанию const функторы в любом случае?
  • Помогает ли на всех , что vector имеет конструктор перемещения и переместить присвоить ?
    • Если да, нужно ли добавлять их также к Image, чтобы предотвратить здесь дорогую копию?
  • Есть ли разница в механизме, когда икак копия требуется для захвата по значению по сравнению с аргументами по значению ?например.void operate(vector<Image> movie)?

Ответы [ 2 ]

9 голосов
/ 12 марта 2011

Я вполне уверен, что не может.

Даже если внешняя функция больше не использует переменную явно, перемещение переменной изменит семантику уничтожения.

Наличие конструкторов перемещения для Image не помогает, vector может move или swap без перемещения его элементов.

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

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

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

3 голосов
/ 15 марта 2011

Существует всегда правило "как будто".Пока выглядит так, как если бы правила были соблюдены, компилятор может делать все что угодно.Таким образом, для объектов, где конструктор копирования и деструктор не имеют побочных эффектов, и где в копию не вносятся изменения или исходный объект не доступен впоследствии (поэтому никто не заметит, если мы внесем изменения в объект), компиляторможет доказать, что удаление копии является законным по правилу «как будто».

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

...