Home > Software engineering >  Can I use std::copy to copy arrays allocated on heap?
Can I use std::copy to copy arrays allocated on heap?

Time:06-15

I am using Qt6, C 11, I declare two 2d arrays of dynamic sizes:

int **A; int **B;
A = new int*[rowCount]();
for(int i = 0; i < rowCount; i  )
{
    A[i] = new int[colCount]();   //Same for B
}
// Then feed A with some incoming values

and I want to copy all A's values to B, I know that using std::copy is faster and cleaner than using for -loop, so I tried:

 std::copy(&A[0][0], &A[0][0] rowCount*colCount,&B[0][0]);

However I got error message:

code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)

Looks like I am trying to access memories not allocated? But I have already allocated two arrays on the heap

Why I don't use 2d vector or list is that I need to process large amount of data and accessing array by index is O(1), if you think this is caused by my compiler I can provide make file and project file snippets. Thank you very much

CodePudding user response:

The issue is that you can't guarantee that each call to new[] will generate consecutive locations for the rows.

Your 2d array is actually a 1d array of pointers to random memory locations. There is no guarantee that the beginning of one row follows the end of the previous row.

So, to copy your 2d array, you'll have to loop through the rows, copying each row separately:

for (int row = 0; row < rowCount;   row)
{
    std::copy(&A[row], &B[row], colCount);
}

If you allocate the 2d array at contiguous locations, you could then use one call to std::copy:

int A[MAX_ROWS * MAX_COLUMNS];
int B[MAX_ROWS * MAX_COLUMNS];
std::copy(&A[0], &B[0], MAX_ROWS * MAX_COLUMNS);

CodePudding user response:

You cannot use std::copy to copy your array as a single chunk because you do not have a single array. What you have is a pointer to the first element of an array of pointers to the first element of arrays of ints. That is, assuming rowCount and colCount are both 3, you have this:

A
┌───┐
│   │
│ │ │
│ │ │
└─┼─┘
  │
  ▼
┌───┐
│   │        ┌───┬───┬───┐
│ ──┼───────►│ 0 │ 0 │ 0 │
│   │        └───┴───┴───┘
├───┤
│   │        ┌───┬───┬───┐
│ ──┼───────►│ 0 │ 0 │ 0 │
│   │        └───┴───┴───┘
├───┤
│   │        ┌───┬───┬───┐
│ ──┼───────►│ 0 │ 0 │ 0 │
│   │        └───┴───┴───┘
└───┘

As you can see, there is no contiguous chunk of elements for std::copy to copy.

If you want to be able to efficiently copy (and access) elements of your array, you should allocate a single array that is rowCount*colCount long. If you want nice syntax you could wrap it up in a class and overload the () or [] operator to make the access nicer. For example:

class Matrix
{
private:
    int rowSize_;
    std::vector<int> storage_;
public:
    Matrix(int rowCount, int colCount)
         : rowSize_{colCount},
           storage_(rowCount * colCount)
    {}

    int& operator()(int row, int col)
    {
        return storage_[row * rowSize_   col];
    }
};

int main()
{
    Matrix mat{3, 3};
    mat(1, 2) = 42;

    // copy with simple copy construction
    Matrix mat2 = mat;

    // or copy-assignment
    mat2 = mat;
}
  •  Tags:  
  • c qt
  • Related