Векторный emplace_back
Не могли бы вы объяснить, как работает "совершенная переадресация"?
Я читал, что вектор emplace_back не нужно копировать и перемещать объекты, потому что его аргумент реализован как вариационный шаблон.
std::vector<T>::emplace_back(_Args&&... __args)
Можете ли вы описать это более подробно? Почему он не копируется и не перемещается?
Ответы
Ответ 1
emplace_back
непосредственно конструирует элемент в правильном положении в векторе. Подумайте об этом, как будто
vector<T> v;
v.emplace_back(a,b,c);
преобразуется в (idx - новый индекс)
new (v.data()+idx) T(a,b,c);
(Реальность немного сложнее, включая перенаправление аргументов как std::forward<_Args>()...
, но это может быть более запутанным для получения ключа операций emplace)
Ответ 2
В emplace_back на самом деле две вещи:
- Вы не передаете объект типа T, а аргументы конструктору T. Таким образом, конструкция объекта задерживается: вектор расширяется для размещения в памяти, необходимой для нового объекта, и конструктор вызывается для инициализировал объект в векторе. Шаблон Variadic не имеет ничего общего с копиями, они позволяют перенаправлять переменное число аргументов конструктору.
- Аргументы для самих конструкторов не копируются, потому что они передаются как ссылки rvalues, а std:: move используется для пересылки их в конструктор. В принципе, перемещение семантики позволяет избежать глубоких копий объектов.