0
votes

how to convert/copy a vector to unique_ptr<int[]> ?

this is what I want to achieve (the vector originates in another context and will be deleted after copying to the unique_ptr. unique_ptr is of fixed length and thus can be allocated more efficiently).

std::vector<int> vv {1, 2, 3};

struct
    U {
        U(std::vector<int> v) { // copy constructor
            // copy vector v to unique_ptr u, HOW?
        }

        std::unique_ptr<int[]> u; 
};


U uu {vv}; // copy vector vv to unique_ptr uu, HOW?

i tried to make a copy constructor

U(std::vector<int> v) {
    u = std::make_unique<int[]>(v.size()); // OK
    std::copy(v.begin(), v.end(), u); // error: u has no copy constructor
}

so, how should I construct the copy constructor?

actually and moreover, once constructed I want the unique_ptr<T[]> to be constant in both length and content, so in my case it should be

std::unique_ptr<int const[]> const u; // const in both length and content

how does the copy constructor look in both cases?

case 1) std::unique_ptr<int[]> u case 2) std::unique_ptr<int const[]> const u

2
for performance reasons, vector is not optimal I don't see how that's possible. An array and a vector have the same performance characteristics.Eljay
for performance reasons, vector is not optimal There is no difference in performance between a std::vector and a std::unique_ptr. Use a vector, it's the tool for the job.NathanOliver
even if there was a difference you would need a lot of difference to justify copying the whole vector463035818_is_not_a_number
You really should explain what your performance concerns are. It is for sure possible to answer your question. But it seems that you have a misunderstanding about why you could have performance problems when using a vector compared to unique_ptr so this should be clearified first.t.niese
unique_ptr is of fixed length and thus can be allocated more efficiently A vector can use reserve which will be allocated just as efficiently.Eljay

2 Answers

1
votes

There are several problems with what you are doing. First you have two copies instead of one (in the U constructor), then as you need to get the actual iterator on your u, not u itself.

For the const correctness, you can just have an intermediate unique pointer that allows the data to be changed.

The final code you have should look like:

struct U {
    U(const std::vector<int>& v) {
        auto data = std::make_unique<int[]>(v.size());
        std::copy(v.begin(), v.end(), data.get());
        u = std::move(data);
    }

    std::unique_ptr<int const[]> u; 
};

To note: a vector is as efficient as your unique pointer. The data access pattern are going to be the same. The overhead is only if you push_back to it, or erase. As you are not doing any of these, just store a const vector.

If you wanted a const std::unique_ptr<int const[]> u, then you need to add a static method that will convert your vector into a std::unique_ptr<int const[]> and your constructor would take a && on it and move it in u in the init list.

struct U {
    U(std::unique_ptr<int const[]>&& u)
    : u(std::move(u)) {}

    static U create(const std::vector<int>& v) {
        auto data = std::make_unique<int[]>(v.size());
        std::copy(v.begin(), v.end(), data.get());
        std::unique_ptr<int const[]> u = std::move(data);
        return U(std::move(u));
    }

    const std::unique_ptr<int const[]> u; 
};
1
votes

i tried to make a copy constructor

That's not a copy constructor. That's a converting constructor.

std::copy(v.begin(), v.end(), u); // error: u has no copy constructor

The third argument of std::copy must be an iterator just like the first two. std::unique_ptr is not an iterator.

The unique pointer points to an array. A pointer is an iterator for array. So, what you need is a pointer. How to get a pointer from a unique pointer? Use std::unique_ptr::get member function.

You can make the constructor much more generic by accepting templated iterators (or a range) rather than a vector. As a bonus, you avoid copying twice (which can also be avoided by using a reference).

unique_ptr is of fixed length and thus can be allocated more efficiently

There is little difference in how a vector and a dynamic array such as one managed by a unique pointer can be allocated. Even if there is some difference, copying the input vector for conversion is going to be much less efficient than not copying it.