Редактировать (Новый и правильный ответ)
Извините, если присмотреться к коду, кажется, что ответ гораздо проще: вы никогда не вызываете конструктор перемещения.Вы никогда не двигаете объект.Вы просто передаете rvalue ссылку на функцию work
, которая вызывает функцию-член для этой ссылки , которая все еще указывает на исходный объект.
Исходный ответ сохранендля потомков
Чтобы действительно выполнить ход, у вас должно быть что-то вроде Foo f3(std::move(f2));
внутри work
.Затем вы можете вызвать функцию-член на f3
, который является новым объектом, созданным путем перемещения из f
Насколько я вижу, вы вообще не получаете семантику перемещения.Вы просто видите старую копию elision.
, чтобы перемещение произошло, вы должны использовать std::move
(или, в частности, передаваемый конструктору аргумент должен быть безымянной / временной) ссылкой на значение.например, тот, который возвращается из std::move
).В противном случае он обрабатывается как простая старомодная ссылка lvalue, и затем должно произойти копирование , если , но, как обычно, компилятору разрешается оптимизировать его, оставляя вам один конструируемый объект и один объектбыть уничтоженным.
В любом случае, даже с семантикой перемещения, нет причины, по которой компилятор не должен делать то же самое: просто оптимизировать перемещение, как если бы он оптимизировал копирование.Перемещение дешево, но все же дешевле просто построить объект там, где он вам нужен, а не построить его, а затем переместить его в другое место и вызвать деструктор для первого.
Также стоит отметитьчто вы используете относительно старый компилятор, и в более ранних версиях спецификации было очень неясно, что должно происходить с этими "объектами-зомби".Так что возможно, что GCC 4.3 просто не вызывает деструктор.Я полагаю, что только последняя ревизия или, может быть, та, что была до нее, явно требует, чтобы деструктор был вызван