std::copy for dynamically allocated pointers - c++

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.

Related

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

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.

Create an Array of vectors in C++

I want to create a distance matrix of a big dataset, and only want to store the 'close' enough elements. The code reads like this
vector<double> * D;
D = (vector<double> *) malloc(dim *sizeof(vector<double>) ) ;
for(i=0;i<dim;i++){
for(j=i+1;j<dim;j++){
dx = s[j][0] - s[i][0];
dy = s[j][1] - s[i][1];
d = sqrt( dx*dx + dy*dy );
if(d < MAX_DISTANCE){
D[i].push_back(d);
D[j].push_back(d);
}
}
which gives me segmentation fault. I guess I have not defined the array of vector correctly. How do I get around this ?
In C++ you should never allocate object (or arrays of objects) using malloc. While malloc is good at allocating memory, that's all it does. What it doesn't do is calling constructors which means all your vector objects are uninitialized. Using them will lead to undefined behavior.
If you want to allocate an array dynamically you must use new[]. Or, better yet, use std::vector (yes, you can have a vector of vectors, std::vector<std::vector<double>> is fine).
Using the right vector constructor you can initialize a vector of a specific size:
// Create the outer vector containing `dim` elements
std::vector<std::vector<double>> D(dim);
After the above you can use the existing loops like before.

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.

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.

Copying an array into a std::vector

I was searching about this topic and I found many ways to convert an array[] to an std::vector, like using:
assign(a, a + n)
or, direct in the constructor:
std::vector<unsigned char> v ( a, a + n );
Those solve my problem, but I am wondering if it is possible (and correct) to do:
myvet.resize( 10 );
memcpy( &myvet[0], buffer, 10 );
I am wondering this because I have the following code:
IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
uint8_t* data = new uint8_t[totalToRead];
DWORD totalRead;
ReadFile( mhFile, data, totalToRead, &totalRead, NULL );
bufferRead.resize( totalRead );
bufferRead.assign( data, data + totalRead );
delete[] data;
return IDiskAccess::READ_OK;
}
And I would like to do:
IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
bufferRead.resize( totalToRead );
DWORD totalRead;
ReadFile( mhFile, &bufferRead[0], totalToRead, &totalRead, NULL );
bufferRead.resize( totalRead );
return IDiskAccess::READ_OK;
}
(I have removed the error treatment of the ReadFile function to simplify the post).
It is working, but I am affraid that it is not safe. I believe it is ok, as the memory used by the vector is continuous, but I've never seen someone using vectors this way.
Is it correct to use vectors like this? Is there any other better option?
Yes it is safe with std::vector C++ standard guarantees that the elements will be stored at contiguous memory locations.
C++11 Standard:
23.3.6.1 Class templatevector overview [vector.overview]
A vector is a sequence container that supports random access iterators. In addition,itsupports(amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously, meaning that ifv is avector whereT is some type other than bool, then it obeys the identity&v[n] == &v[0] + n for all0 <= n < v.size().
Yes, it is fine to do that. You might want to do myvet.data() instead of &myvet[0] if it looks better to you, but they both have the same effect. Also, if circumstances permit, you can use std::copy instead and have more type-safety and all those other C++ standard library goodies.
The storage that a vector uses is guaranteed to be contiguous, which makes it suitable for use as a buffer or with other functions.
Make sure that you don't modify the vector (such as calling push_back on it, etc) while you are using the pointer you get from data or &v[0] because the vector could resize its buffer on one of those operations and invalidate the pointer.
That approach is correct, it only depends on the vector having contiguous memory which is required by the standard. I believe that in c++11 there is a new data() member function in vectors that returns a pointer to the buffer. Also note that in the case of `memcpy you need to pass the size in bytes not e size of the array
The memory in vector is guaranteed to be allocated contiguously, and unsigned char is POD, therefore it is totally safe to memcpy into it (assuming you don't copy more than you have allocated, of course).
Do your resize first, and it should work fine.
vector<int> v;
v.resize(100);
memcpy(&v[0], someArrayOfSize100, 100 * sizeof(int));
Yes, the solution using memcpy is correct; the buffer held by a vector is contiguous. But it's not quite type-safe, so prefer assign or std::copy.