Скажем, у меня есть вектор некоторых общих объектов T:
std::vector<T> vector_of_ts = {...};
Этот вектор по сути представляет собой массив T-объектов, выделенный в куче. Теперь предположим, что у меня есть следующее:
std::unique_ptr<T> t = std::make_unique<T>(...);
Опять же, под капотом это выделенный в куче T-объект. Можно ли вернуть этот объект в вектор, переместив его, не создавая временных/дополнительных копий? Что-то вроде:
vector_of_ts.move(*t)
Вы можете неправильно понять, что значит «переместить» объект. Независимо от того, выделен объект в куче или нет, это не влияет на то, можно ли его переместить. Кроме того, перемещение объекта обычно предполагает копирование некоторых данных, но не всегда всех данных.
Будьте осторожны с разрезанием объектов при перемещении unique_ptr<T>
в vector<T>
. Если unique_ptr<T>
является полиморфной базой (что, возможно, и является причиной того, что это указатель), вы разрезаете свой объект.
vector_of_ts.emplace_back(std::move(*t))
позволит вам переместить букву T из unique_ptr в вектор: пример
#include <memory>
#include <vector>
struct T
{
// Can't be copied
T() = default;
T(const T&) = delete;
T(T&&) = default;
T &operator=(const T&) = delete;
T &operator=(T&&) = default;
};
int main()
{
std::vector<T> vector_of_ts;
std::unique_ptr<T> t = std::make_unique<T>();
// error: use of deleted function T::T(const T&)
vector_of_ts.emplace_back(*t);
// Success
vector_of_ts.emplace_back(std::move(*t));
}
Обратите внимание, что после перемещения t
указывает на перемещенный из T
объект. Состояние этого объекта зависит от того, что делает конструктор перемещения (например, std-контейнеры остаются в «действительном, но неопределенном» состоянии, что означает, что вам не следует ничего с ними делать, кроме как уничтожить их или переназначить им).
Вы можете переместить и построить новый T
объект в std::vector
так же, как вы перемещаете и построить любой объект, то есть vector_of_ts.push_back(std::move(*t))
, но вы не можете каким-то образом переместить тот же T
объект в вектор.
std::vector<T>
— это непрерывный контейнер. То есть внутри это указатель на один большой динамически выделяемый фрагмент памяти, в котором находится некоторое количество T
объектов.
std::unique_ptr<T>
— это указатель на один динамически выделяемый T
объект.
Вы не можете «добавить» объект T
, на который указывает std::uniqeu_ptr
, к std::vector
, поскольку он не является частью непрерывного блока памяти, управляемого std::vector
.
Нет, вектор — это не массив указателей, это непрерывный массив. Вы можете использовать конструктор перемещения объекта, чтобы переместить его в вектор, но это будет новый объект.