Can I move a std::unique_ptr<T> into a std::vector<T>?

115 Views Asked by At

Say I have a vector of some generic T objects:

std::vector<T> vector_of_ts = {...};

That vector is basically a heap-allocated array of T objects, under the hood. Now, say I have the following:

std::unique_ptr<T> t = std::make_unique<T>(...);

Again, this is a heap-allocated T object under the hood. Is it possible to push back that object to the vector by moving it, without making temporary/extra copies? Something like:

vector_of_ts.move(*t)
2

There are 2 best solutions below

0
Kevin On BEST ANSWER

vector_of_ts.emplace_back(std::move(*t)) will let you move the T from the unique_ptr into the vector: example

#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));
}

Note that after the move, t points to the moved-from T object. The state of this object depends on what the move constructor does (std containers for example are left in a "valid but unspecified" state, meaning you shouldn't do anything with them except destroy them or reassign to them).

0
Miles Budnek On

You can move-construct a new T object in the std::vector in the same way you move-construct any object, i.e. vector_of_ts.push_back(std::move(*t)), but you can't somehow move the same T object into the vector.


A std::vector<T> is a contiguous container. That is, under the hood it's a pointer to one big dynamically-allocated chunk of memory in which some number of T objects reside.

A std::unique_ptr<T> is a pointer to a single dynamically-allocated T object.

You can't "add" the T object pointed to by the std::uniqeu_ptr to the std::vector because it isn't a part of the contiguous memory block managed by the std::vector.