Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to move an std::array into a std::vector?

This is a question about the interaction of stack memory and heap memory and the particular case of going from stack to heap via the std::array and std::vector classes.

In principle std::array<T> can be seen as a pointer to the first elements, plus some compile time information about the size of the array. Would it be possible to have std::vector<T> constructor that takes into account that fact and tries to move contents of the array into the vector just by copying the pointer.

A use case would be, that one has a function that returns a std::array<double, >

std::array<double, 20> fun(){...};

but one later decides to assign it to a std::vector without the necessity of copying element by element.

std::vector<double> v = fun(); // not working code

Right now one has to do

std::array<double, 20> tmp = fun();
std::vector<double> v(tmp.begin(), tmp.end());

Which actually does some redundant work which wouldn't be necessary if this were possible std::vector<double> v(std::move(tmp)); \\ not working code.

The memory layout of std::vector and std::array is the same, so that is not and obstacle.

I understand that the main obstacle could be that std::array elements are in the stack while std::vector elements are in the heap. It is clear that even if one writes the move constructor for std::vector still the memory from the stack will be irrevocably destructed.

So I guess that this question can also be read as:

Is there a way to move memory from the stack to the heap (whatever that means) and if that can be combined with a move constructor?

Or if std::vector can have in principle a move constructor from a std::array?

MWE:

#include<array>
#include<vector>

std::array<double, 20> fun(){return {};} // don't change this function

int main(){
    std::array<double, 20> arr = fun(); // ok
    std::vector<double> v(arr.begin(), arr.end()); // ok, but copies and the allocation is duplicated
    std::vector<double> v2 = fun(); // not working, but the idea is that the work is not duplicated
}
like image 604
alfC Avatar asked Dec 01 '15 11:12

alfC


People also ask

Can you pass an array to a vector?

Using an Existing ArrayYou can initialize a vector by using an array that has been already defined. You need to pass the elements of the array to the iterator constructor of the vector class. The array of size n is passed to the iterator constructor of the vector class.

Can I assign an array to a vector C++?

In C++, the Vector class provides a constructor which accepts a range, so to create a vector from array elements, pass the pointer to the first and last position of the range as the argument during the vector initialization that needs to be copied to the vector i.e, (arr, arr+N).

What is the difference between std :: array and std::vector?

Difference between std::vector and std::array in C++Vector is a sequential container to store elements and not index based. Array stores a fixed-size sequential collection of elements of the same type and it is index based. Vector is dynamic in nature so, size increases with insertion of elements.


1 Answers

It seems like you want to tell std::vector to use the std::array data as its underlying buffer, at least until it needs to do some reallocation.

std::vector does not have an interface for this. It is supposed to manage its internal buffer itself, so memory is allocated, tracked and deleted in a unified manner. If you could provide a buffer to use, you would also need to supply information about how it was allocated, if it might get destroyed on leaving a scope, etc. This is error prone and ugly, so is not available.

What you can do is construct the std::vector with std::move_iterators to move the contents out of the std::array. Of course, this won't make a difference for arithmetic types, but for logically large objects which are cheap to move it can avoid a lot of data copying:

std::array<BigThing, 20> a = fun();
std::vector<BigThing> b { std::make_move_iterator(a.begin()),
                          std::make_move_iterator(a.end())) };
like image 109
TartanLlama Avatar answered Oct 01 '22 03:10

TartanLlama