Ответ 1
Я думаю, что это скорее вопрос философии, чем техника:)
Основной вопрос заключается в различии между Move and Copy. Я не буду вникать в технический/стандартизированный язык, давайте сделаем это просто:
- Копировать: создать другой идентичный объект (или, по крайней мере, тот, который ДОЛЖЕН сравняться с равным)
- Переместить: взять объект и поместить его в другое место
Как вы сказали, возможно реализовать Move in the terms of Copy: создать копию в новом месте и отбросить оригинал. Однако есть два вопроса. Один из них имеет производительность, второй - объекты, используемые для RAII: какой из двух должен иметь право собственности?
Правильный конструктор Move решает два вопроса:
- Ясно, какой объект имеет собственность: новый, так как оригинал будет отброшен
- Таким образом, нет необходимости копировать указанные ресурсы, что позволяет повысить эффективность
Символы auto_ptr
и unique_ptr
являются очень хорошей иллюстрацией этого.
С помощью auto_ptr
у вас есть привинченная семантика копирования: оригинал и копия не сравниваются одинаково. Вы можете использовать его для семантики Move, но существует риск того, что вы потеряете объект, на который указывает где-то.
С другой стороны, unique_ptr
- это именно то, что: он гарантирует уникального владельца ресурса, что позволяет избежать копирования и неизбежной проблемы удаления, которая будет следовать. И без копий гарантируется время компиляции. Поэтому он подходит в контейнерах, если вы не пытаетесь инициализировать копию.
typedef std::unique_ptr<int> unique_t;
typedef std::vector< unique_t > vector_t;
vector_t vec1; // fine
vector_t vec2(5, unique_t(new Foo)); // Error (Copy)
vector_t vec3(vec1.begin(), vec1.end()); // Error (Copy)
vector_t vec3(make_move_iterator(vec1.begin()), make_move_iterator(vec1.end()));
// Courtesy of sehe
std::sort(vec1.begin(), vec1.end()); // fine, because using Move Assignment Operator
std::copy(vec1.begin(), vec1.end(), std::back_inserter(vec2)); // Error (copy)
Таким образом, вы можете использовать unique_ptr
в контейнере (в отличие от auto_ptr
), но ряд операций будет невозможным, поскольку они связаны с копированием, который тип не поддерживает.
К сожалению, Visual Studio может быть довольно слабым в применении стандарта, а также имеет ряд расширений, которые вам необходимо отключить, чтобы обеспечить переносимость кода... не используйте его для проверки стандарта:)