С++ 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. Правила регулярного копирования не распространяются на этот случай.