Функции перемещения точно не исключают временные копии.
Существует такое же количество временных библиотек, просто вместо обычного вызова конструктора копирования вызывается конструктор перемещения, который может каннибализировать оригинал, а не создавать независимую копию. Иногда это может быть намного эффективнее.
Формальная объектная модель C ++ никак не изменяется семантикой перемещения. У объектов по-прежнему есть четко определенное время жизни, начиная с определенного адреса и заканчивая тем, что они там уничтожаются. Они никогда не «двигаются» в течение своей жизни. Когда они «перемещаются от», на самом деле происходит то, что кишки извлекаются из объекта, который должен скоро умереть, и эффективно помещаются в новый объект. Может показаться, что они переместились, но формально на самом деле это не так, поскольку это полностью сломало бы C ++.
Перемещение - не смерть. Перемещение требуется, чтобы оставить объекты в «допустимом состоянии», в котором они все еще живы, а деструктор всегда будет вызываться позже.
Удаление копий - это совсем другое дело, когда в некоторой цепочке временных объектов некоторые промежуточные объекты пропускаются. Компиляторы не обязательны для исключения копий в C ++ 11 и C ++ 14, им разрешено делать это, даже если это может нарушить правило «как если бы» это обычно направляет оптимизацию. То есть, даже если ctor копирования может иметь побочные эффекты, компилятор при высоких настройках оптимизации все равно может пропускать некоторые временные файлы.
Напротив, "гарантированное копирование эллисии" - это новая функция C ++ 17, что означает, что стандарт требует, чтобы в определенных случаях выполнялось копирование эллипса.
Семантика перемещения и копирование дают два разных подхода к обеспечению большей эффективности в этих сценариях «цепочки временных файлов». В семантике перемещения все временные библиотеки все еще существуют, но вместо вызова конструктора копирования мы можем вызвать (надеюсь) менее затратный конструктор, конструктор перемещения. В копировальной эллисии мы можем пропустить некоторые объекты вместе.
В принципе, почему семантика перемещения считается особой, а не просто оптимизацией компилятора, которую могли бы выполнить компиляторы до C ++ 11?
Семантика перемещения не является «оптимизацией компилятора». Это новая часть системы типов. Семантика перемещения происходит даже тогда, когда вы компилируете с -O0
на gcc
и clang
- это вызывает вызов разных функций, потому что тот факт, что объект вот-вот умрет, теперь "аннотируется" в типе ссылка. Он позволяет «оптимизацию на уровне приложения», но это отличается от того, что делает оптимизатор.
Может быть, вы можете думать об этом как о страховочной сетке. Конечно, в идеальном мире оптимизатор всегда удалял бы все ненужные копии. Однако иногда создание временного объекта является сложным, включает в себя динамическое выделение памяти, и компилятор не видит всего этого. Во многих таких случаях вас спасет семантика перемещения, которая может позволить вам вообще избежать динамического распределения. Это, в свою очередь, может привести к сгенерированному коду, который затем будет легче анализировать оптимизатору.
Это похоже на то, что они нашли способ формализовать некоторые из этого "здравого смысла" в отношении временных файлов, так что больше кода не только работает так, как вы ожидаете, когда он будет оптимизирован, но и требуется em>, чтобы он работал так, как вы ожидаете, когда он будет скомпилирован, и не вызывать конструктор копирования, когда вы думаете, что на самом деле копии не должно быть. Таким образом, вы можете, например, возвращать не копируемые, не перемещаемые типы по значению из фабричной функции. Компилятор выясняет, что копирование не происходит намного раньше в процессе, еще до того, как оно попадает в оптимизатор. Это действительно следующая итерация в этой серии улучшений.
person
Chris Beck
schedule
06.12.2016
func
... и могут быть обращения к нему в других единицах перевода ... вы выходите из параметра или нет? - person M.M   schedule 06.12.2016