10

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!

3
  • 1
    Oh gosh. Just use vectors please, and it will just work. vec1 = vec2; Commented Mar 31, 2015 at 18:28
  • Yeah it would make my life so much easier, it just happens that I didn't decide to use arrays like that and now they're being used all over the code base. Commented Mar 31, 2015 at 18:35
  • I would seriously consider rewriting it. Vectors have so many advantages, such as bounds checking on good debug compilers. Commented Mar 31, 2015 at 18:42

1 Answer 1

43

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];
Sign up to request clarification or add additional context in comments.

6 Comments

Oh of course, can't believe I didn't realise that. Makes a lot of sense why it wasn't working now. However, I don't see a resolution short of using for loops if I still want to use this array setup?
If height is a constant, it can be done, i.e getting a 2D array with new. But is it?
@KieronH See stackoverflow.com/questions/936687/… for more information
@KieronH: I edited in an approach that I think you might find useful.
Wow, that's ingenious!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.