С++ 0x: Capture By Value для Lambda, всегда копия?

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

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

Ответы

Ответ 1

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

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

Перемещение конструкторов для Image не помогает, a vector может move или swap не перемещать свои элементы.

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

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

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

Ответ 2

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

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