Валидный будет и там, и там. 11 стандарт дал возможность вылавливать объекты, которые временные или вот-вот умрут (через перегрузку, сигнатуры с rvalue). Без move вы полностью копируете item (внутренний стринг, выделяя место в хипе, вызывается дефолтный оператор= с lvalue). С move же можно просто забрать ресурсы у умирающего объекта и не делать дорогих телодвижений в хипе (вызовется дефолтный оператор= с rvalue). Конечно, можете тянуть шлейф указателей и указателей на указатели (если необходимо заменить объект другим внутри алгоритма). Или же делать сделать в стиле чистого Си:
void copy(Obj &dest, Obj &src) {
/* здесь проиводим полное копирование (открываем новые хенделы на какие-то
* ресурсы (семафоры, мьютексы, память, что угодно еще). На выходе два
* имеем два валидный объекта
*/
}
void copy_from_temp(Obj &dest, Obj &src) {
/* здесь забираем ресурсы у src (не открываем новые хенделы на какие-то
* ресурсы (семафоры, мьютексы, память, что угодно еще). На выходе один
* валидный объект - dest
*/
}
Конечно, если внутри Obj не хранит никаких ресурсов, то разницы в этих функциях
не бдет никакой. Новые кресты делают за нас львиную долю всей этой возни - сами
поймут, что объект временный (иногода можно подсказать), вызовут нужную перегрузку,
сущности из стд умеют правильно перемещаться (что покрывает 90% нужд).
Спасисбо за развернутый ответ. Ну хотелось бы избежать ненужных копиований, это же время.
Делаю вообще вот так:
items.push_back(std::move(Foo(s))),