Copy 2D array using memcpy?
So I want to copy the contents of a 2D array to another array of the exact same type. Here is how the array is created:
GridUnit** newGrid;
newGrid = new GridUnit*[width];
for (int i = 0; i < width; i++)
newGrid[i] = new GridUnit[height];
GridUnit is size 16 (4 floats). So that's all initialised fine, no problems with using it as it is after I have ran the for loops to actually fill the values with some data. Now what I want to do is copy the contents of another array into this one (without for loops if possible). This is what I have been trying to do so far:
memcpy(&newGrid, &grid, height * width * 16);
'grid' is identical to 'newGrid' in terms of its size and type. However, this does not work. I know the memcpy is possibly not correct, but having tried multiple different setups using this, I don't know what's going wrong with it anymore, so any help would be welcome!
Solution 1:
If you actually had a 2-D array, that memcpy
call would work. But you don't, you have width
separate discontiguous 1-D arrays, collected in an array of pointers.
It is possible to dynamically allocate a contiguous block where row and column count both vary at runtime, and preserve the two-subscript access. You'll have to change the allocation code as follows:
GridUnit** newGrid;
newGrid = new GridUnit*[width];
newGrid[0] = new GridUnit[width * height];
for (int i = 1; i < width; i++)
newGrid[i] = newGrid[i-1] + height;
Deallocation becomes simpler:
delete[] newGrid[0];
delete[] newGrid;
There's no delete[]
for newGrid[i]
with i > 0
because they don't have their own blocks, they just point into the single large block. Because everything is contiguous, you can think of newGrid[0]
either as a pointer to the first row (height
elements), or the entire 2-D array (width * height
elements).
And you can then access all the data as a single contiguous block:
memcpy(newGrid[0], oldGrid[0], height * width * sizeof newGrid[0][0]);
Of course, one shouldn't use raw pointers for memory ownership. A smart pointer will ensure the memory is properly deleted even with exceptional flow control. It would look like this:
std::unique_ptr<GridUnit[]> newData;
std::unique_ptr<GridUnit*[]> newGrid;
// before C++14 use // newData.reset(new GridUnit[width * height]);
newData = std::make_unique<GridUnit[]>(width * height);
// before C++14 use // newGrid.reset(new GridUnit*[width]);
newGrid = std::make_unique<GridUnit*[]>(width);
for (int i = 0; i < width; i++)
newGrid[i] = &newData[i * height];