How to assign C++ array with a pointer to first element? - c++

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)?

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

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

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:
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.
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.

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.

Related

Why is std::copy throwing an error vector iterator + offset out of range and not able to copy

I was trying to copy an int array into std::vector of int and I am seeing some unusual behavior. So I have an array as defined as below.
int myarray[10] = {1,2,3,4,5,6,7,8,9,10};
and I tried copying the above array into vector using different methods as below which throws errors.
1) Using reserve
std::vector<int> vec1;
vec1.reserve(10);
std::copy(myarray, myarray+10,vec1.begin() );
This throws an error in VS 2013 which is :-
vector iterator + offset out of range
2) By defining size
std::vector<int> vec2(10);
std::copy(myarray, myarray+10,vec2.begin() );
Which successfully copies the array into the vector.
3) Just declaring the vector .
std::vector<int> vec3;
std::copy(myarray, myarray+10,vec3.begin() );
Which also throws an error
vector iterator + offset out of range
Also searching over the internet I found that std::back_inserter could be used, but I don't know what difference it would make.
Can some please explain the difference between all the three methods and whats going wrong in 1 and 3.
Instead of vec1.reserve(10); use vec1.resize(10);
std::vector::reserve would increase the capacity of vector but the size remains same. It requests that the vector capacity be at least enough to contain n elements.
On the other hand, std::vector::resize resizes the container so that it contains n elements
As #Mohit Jain's answer shows resize would help. But that initializes the vector which is not needed. For integers it might not be a problem but for big objects it's definitely a performance overhead.
reserve can help here if you use std::copy as shown below.
std::vector<int> vec2(10);
vec2.reserve(10);
std::copy(myarray, myarray+10, std::back_inserter(vec));
BTW, you can also copy the contents of the array to the vector during the construction of the vector itself.
std::vector<int> vec2 ( myarray, myarray + 10);

C++ copying and resizing an allocated array initialized using the new operator

int* array1 = new[ 10 ]( );
What is the correct way to copy this array? The following is my attempt.
int* array2 = array1;
With that said, is the following the correct way to add a value to a full array1?
int val = 2;
int* array2 = new[ 11 ]( );
for ( int i = 0; i < 10; i++ ) {
array2[ i ] = array1[ i ];
}
array2[ 10 ] = val;
delete [ ]array1;
One more question, how do I get the amount of spaces that are filled in an array?
int* array1 = new[ 2 ];
array1[ 0 ] = 1;
// the resulting array would look like this { 1 };
I want to get the number of initialized elements, so instead of returning 2 for the number of elements the allocated array can hold, I want to get how many elements actually have a value. I want to do this so I can replace the 10 in my previous code with the size of array1.
Thank you!
EDIT: I need to stick with c style arrays because of my instructor.
int* array2 = array1;
assigns one pointer to another, i.e. it copies an address stored in array1 and makes array2 to point to this address as well.
If you want to make a deep copy while still using pointers you could use memcpy:
int* array2 = new int[10];
memcpy(array2, array1, 10 * sizeof(int));
which is ghastly C-style approach that you should avoid always when it is possible.
The only reasonable solution that I can think of is using std::array or std::vector instead of
C-style arrays. std::vector unlike an array is an object that has its own assignment operator (as well as copy constructor) that copies it for you the way you would expect it:
std::vector<int> vec1(10, 0); // 10 numbers initialized to 0
std::vector<int> vec2 = vec1; // note this actually calls copy constructor
std::vector<int> vec3(vec1); // the same as previous line
vec3 = vec1; // assignment that makes a deep copy for you
You can start with an empty std::vector and keep pushing new elements to it using its push_back method and retrieve its size at any time calling vec.size(). Additionally: you are not responsible for cleaning up the memory where its elements were stored - if you use it as I pointed out in the above code, these are objects with automatic storage duration that clean up the memory for you when they go out of scope.
Your first attempt doesn't copy the contents of the array, it simply creates a new pointer that points to the beginning of the array.
Your method of adding a value looks correct.
The array itself does not remember which members you have assigned values to. If you want to keep track of how many elements are "filled", you'll have to do that yourself. You could wrap the array in, say, a template class, and perhaps call it myVector.

std::copy for dynamically allocated pointers

This is probably a very newbie question. The class I'm working on (let's call it MyClass) contains the following variables
int nbins;
double * bins; // = new double[nbins+i]
Since I'm implementing a copy constructor
MyClass( const MyClass& source )
I need to copy source.bins. I was going to use std::copy from algorithm, but all the examples I've found show how to copy static array like double bins[] = ... or standard data structure like std::vector. I can't find any example in which std::copy is used on pointers like double * bins = new double[nbins+i]. So, my question is: is legal to use std::copy on pointers, like for example
double * bins = new double[nbins+1]; //is this necessary?
std::copy( std::begin( source.bins ), std::end(source.bins), std::begin(bins) );
or should I rather rely on the C memcpy
double * bins = new double[nbins+1]; //again, is this necessary?
memcpy( source.bins, bins, (nbins+1) /* *sizeof(double) ?*/ );
So, my questions are basically two:
1) Does std::end(bins) know where is the end of bins (=new double[nbins+1])?
2) Do I need to allocate the memory for the destination before doing the copy? Or the copy (or memcpy) takes care of that?
1) Does std::end(bins) know where is the end of bins (=new double[nbins+1])?
No, std::begin and std::end require that the array be of fixed size.
2) Do I need to allocate the memory for the destination before doing the copy? Or the copy (or memcpy) takes care of that?
You need to allocate the memory. Both copy and memcpy assume that you provide them with a block of memory that can be written to.
So yes, you can use std::copy, but without std::begin and std::end:
double * bins = new double[nbins+1]; //is this necessary?
std::copy( source.bins , source.bins + N, bins );
where N is the length or the array pointed at by source.bins. Obviously you have to make sure you are not accessing either array out of bounds.

std::vector size remains zero after trying to fill it

I'm trying to use vector efficiently. So I reserve memory first and then use the vector. But after I try to fill the vector using [] operator, the size of vector remains zero. Why does this happen?
vector Vec;
Vec.reserve(10);
Vec[0] = 2.0;
Vec[1] = 3.0;
...
reserve() only reserves space in the backing store so subsequent pushed elements don't have to incur a reallocation (until you exceed the reserved space). It doesn't change the actual size of the vector though, so your Vec[0] = access is actually running off the end of the vector.
You could use
vector Vec;
Vec.resize(10);
Vec[0] = 2.0;
Vec[1] = 3.0;
if you want, and the size will be 10. Or if you want the size to only be 2 at this point, but still reserve space to avoid multiple reallocations, you could use
vector Vec;
Vec.reserve(10);
Vec.push_back(2.0);
Vec.push_back(3.0);
reserve() doesn't resize the vector. You need to use resize().
When you use reserve you aren't actually creating elements in the vector. Your assignments are accessing elements that don't exist.
std::vector does not automatically expand. Function reserve(size) does not increase the size, it can only make sure you have enough memory for later size expansion.
So instead of the illegal
Vec[0] = 2.0;
Try
Vec.push_back( 2.0 );
This will increase the vector size by 1.
By the way, the declaration should be
vector<double> Vec;
reserve has no effect on the size of the vector. On most
implementations I've used, the following accesses would have
caused the program to terminate. If it didn't, you probably
compiled with the wrong options.
You should construct the vector directly with a size of 10:
std::vector<double> vec( 10 );
If the values you are inserting are constants, you can do
something like:
static double initVec[] = { 2.0, 3.0 ... };
std::vector<double> vec( begin( initVec ), end( initVec ) );
, or if you are using C++11:
std::vector<double> vec{ 2.0, 3.0 ... };
Both of these methods have the advantage of initializing the
data in the vector directly.

copy of an array into a vector not happening as expected

I am trying to copy an array to a vector.
int A[1000]; //This array is filled by some function
vector<int> vec;
//some position from which I want to write the contents of the array into vector
int x = some_position;
vec.resize(sizeof(A)+x);
vec.insert(vec.begin()+x, A, A+sizeof(A));
The problem is that every fourth element is not copied correctly. The rest of the elements are copied correctly. i.e vec[x+3] != A[x+3]
for x=0,1,2,3....
First off, you need to check your understanding of sizeof. It returns the number of bytes needed for A as a whole, not the number of items in A, for that you would need sizeof(A)/sizeof(*A).
int A[1000];
vector<int> vec;
int x = 5;
vec.resize(x + sizeof(A) / sizeof(*A));
vec.insert(vec.begin()+x, A, A + sizeof(A) / sizeof(*A));
It's also worth noting that 'insert' may not be what you want. If your objective is to treat the vector like an array and overwrite a 1000 element long section of the vector, then you should use std::copy instead. Insert will resize the array even more, so if the resize will make the vector 1005 elements long, and them you start inserting at position 5, then the final vector will be 2005 elements long, with the contents of A going from 5 - 1004.
You could instead replace the insert line with this:
std::copy(A, A + sizeof(A) / sizeof(*A), vec.begin() + x);
This would overwrite the contents of the vector starting at position 5 and leave the vector sized at 1005.
The better way to copy array to vector:
vec.resize(1000+some_position);//if needed
std::copy(A,A+1000,vec.begin()+some_position);
It seems you believe sizeof() gives number of elements
e.g.
vec.resize(sizeof(A)+x);
but it doesn't. it gives the number of bytes.
the correct resizing should be something along the lines of
vec.resize(sizeof(A)/sizeof(int)+x);
of that follows that
vec.insert(vec.begin()+x, A, A+sizeof(A)/sizeof(int));
although I agree with Sergey that copy() is the better (more elegant) way to do it.
Your use of sizeof is wrong. sizeof is a very primitive operator,
which returns the number of bytes in the shallow image of the object
or type. This is totally useless except for very low level programming.
If you need to deal with C style arrays, there functions std::begin()
and std::end() in C++11; in earlier versions of C++, we just wrote
them ourselves. (I usually also wrote a size() function, which
basically returned the number of elements.) And std::vector works in
number of elements, not number of bytes. So your last two lines of code
should be:
vec.resize( x );
vec.insert( vec.end(), std::begin( A ), std::end( A ) );
At least, that's what I think you're trying to do, based on the
comments: create an std::vector<int> with x elements initialized to
0, followed by the contents of A.
Replace sizeof(A) with sizeof(A) / sizeof(A[0]) and it will work.
And as #Sergey pointed out, vec.resize(); in unnecessary in this case as insert() also resizes the vector.
don't copy an array into a vector. Use C++ to avoid that altogether. Instead of
void fill_array(int*, size_t);
int A[1000];
fill_array(A,1000);
std::vector<int> vec;
my_copy(vec,A);
simply do
std::vector<int> vec;
vec.resize(1000); // or whatever
fill_array(vec.data(),vec.size()); // std::vector::data() is C++11
In C++ (also pre C++11) you would actually do this more like this:
template<typename iterator> fill_data(iterator begin, iterator end);
std::vector<int> vec;
vec.resize(n); // make space (otherwise fill_data cannot fill in anything)
fill_data(vec.begin(), vec.end());
then your fill_data is generic enough to be re-used for any type of container.