1

I apologize that I am still very new with C++, so your patience is appreciated.

As part of an un-alterable constraint in my project, I must convert a Vector to an Array. In my searching for a solution I have repeatedly come across answers like this one.

As I understand, that solution gives you a pointer to the first element in the vector -- and since a vector is guaranteed to be contiguous in memory you can then set the array to point to that memory location (or something like that).

My question is, though, how exactly do I do that in C++? The answer seems to suggest it is trivial, but I can't find how to do it.

I have tried things of this nature but they don't work....

std::vector<double> v;
double* a = &v[0];
double myArray[100];
&myArray[0] = a;

Given a pointer to the first element in a sequence, how do I then use that pointer to 'populate' an array? Furthermore, do I have to worry about size differences/going out of bounds issues? Also, could I do this in reverse as well ('populate' a vector with a pointer to the first element of an array)?

Community
  • 1
  • 1
Fortis
  • 43
  • 2
  • 8
  • `double* a = &v[0];` should work – Rakete1111 May 19 '16 at 21:29
  • 1
    @Rakete1111 So then I can use a as an array? e.g. a[3] = 1.5; – Fortis May 19 '16 at 21:32
  • 2
    @user2453459 It is not clear what you are trying to do. – Vlad from Moscow May 19 '16 at 21:40
  • 1
    Arrays aren't assignable in C++. – Kerrek SB May 19 '16 at 21:45
  • An array has its own storage, you can't declare an array to refer to some other storage. – M.M May 19 '16 at 21:59
  • @VladfromMoscow Ultimately, what I needed to know was how to use `a` from this line `double* a = &v[0];` I also needed to know any things to be careful of when using `a`. Then I was curious to know if I could reverse the process and use a pointer to an array to insert back into a vector. All parts of my question have been answered very well between the multiple comments and answers -- and then some very interesting answers which taught me things I didn't know to ask. My only problem now is that I don't know which answer to mark as accepted! – Fortis May 20 '16 at 01:33

4 Answers4

5

You cannot insert elements into a vector using a pointer to the vector's first element. A vector uniquely owns its contents, and therefore must allow you to change its size only using its own interface, otherwise it cannot keep track of how many elements it owns.

You can do this:

std::vector<double> v(N); // N elements initialized to 0.0
double* a = v.data();
do_something(a, N); // tell the function to write N elements
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
1

If you have a vector and an array as for example

std::vector<double> v;
double myArray[100];

and want that the array would contain elements of the vector you should copy elements of the vector in the array as for example

std::copy( v.begin(), 
           std::next( v.begin(), std::min<std::vector<double>::size_type>( v.size(), 100 ) ),
           std::begin( myArray ) );

or

std::copy( v.begin(), 
           v.begin() + std::min<std::vector<double>::size_type>( v.size(), 100 ),
           myArray );

If you want that the vector would have elements of the array then you can write

v.assign( std::begin( myArray ), std::end( myArray ) );

or

v.insert( v.end(), std::begin( myArray ), std::end( myArray ) );

Or you can declare the vector and initialize it at the same time (after defining and filling the array)

std::vector<double> v( std::begin( myArray ), std::end( myArray ) );

that is the same as

std::vector<double> v( myArray, myArray + 100 );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

It depends on the lifetime of the array and vector, as well as how you plan on using the array.

If you merely want to access the vector as an array, you can do it as simply as you have written:

double* myArray = &v[0];

Or, using C++11 or higher:

double* myArray = v.data();

Then you may access the vector as if it were an array using myArray. Effectively, this just aliases the vector's internal memory to a separate pointer. The subscript operator [] works on pointers, thus allowing myArray to more or less function as an array.

However, there are two gotchas with this:

  1. the above will only work correctly if the lifetime of myArray is fully encompassed by that of v. If the vector goes out of scope, is cleared, or is resized, myArray is invalidated. You are merely pointing to the internal memory of v, so anything that changes that memory will break myArray.
  2. As written in your example, this operation is not valid to begin with, as your vector v has no size. Give it a size before taking its address.

If you want to copy the contents of the vector to an array, you can use memcpy().

double* myArray = new double[v.size()];
memcpy( myArray, &v[0], v.size() * sizeof( double ) );

This will allocate the number of elements currently in v in myArray and populate that memory with the data contained in v. However, any changes to myArray will be independent of v. You merely copied the vector into the array.

There are several other ways to accomplish the second option.

  • `std::fill` would be preferable to `memcpy` as then there is not the possibility of making a mistake with `sizeof` – M.M May 19 '16 at 22:04
  • Very informative answer! In my particular circumstance, the goal is to have a method return a vector, which would then need to be converted to an array in order to instantiate an object which needed that array as a data member. So it sounds like I would probably run into a scope issue with your gotcha #1. – Fortis May 20 '16 at 01:27
0

It is possible to make an array reference:

vector<double> v(100);   // must size the vector first, or at least add 1 element and call reserve(100)
double (&myArray)[100] = reinterpret_cast<double(&)[100]>(v[0]);

Then you can use myArray[0], myArray[1] etc. However if you insert into the vector then myArray becomes invalid (and it is not possible to 'move' it).

Although this is possible it would be very unusual so you should not do it in any real code.

M.M
  • 138,810
  • 21
  • 208
  • 365