memcpy и двумерные массивы

Я некоторое время использовал memcpy с одномерными массивами, но когда я пытаюсь использовать двумерные, происходят странные вещи. Следующая программа иллюстрирует проблему:

using namespace std;
#include <iostream>  
#include <string.h>
#include <complex>

int main() {

    int n=4;
    complex<double> **mat1=new complex<double>*[n], **mat2=new complex<double>*[n];
    for(int i=0;i<n;i++) {mat1[i]=new complex<double>[n]; mat2[i]=new complex<double>[n];}

    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) mat1[i][j]=complex<double>(i*j, i+j);
    }

    cout << endl << "Matrix 1:" << endl;
    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) cout << mat1[i][j] << "  ";
        cout << endl;
    }

    cout << endl << "memcpy" << endl << endl;
    memcpy(mat2, mat1, n*n*sizeof(complex<double>));

    cout << "Matrix 1:" << endl;
    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) cout << mat1[i][j] << "  ";
        cout << endl;
    }

    cout << endl << "Matrix 2:" << endl;
    for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) cout << mat2[i][j] << "  ";
        cout << endl;
    }
}

Первая распечатка mat1 работает нормально, но во второй и mat2 первая половина элементов тарабарщина. Есть идеи, что происходит?


person jorgen    schedule 13.08.2014    source источник
comment
Не используйте memcpy в C++, так как это плохо работает с классами. Используйте vector<vector<complex<double>>> mat1(Y, vector<complex<double>>(X)); для вашего 2d-массива. Чтобы скопировать mat2 = mat1;   -  person Neil Kirk    schedule 13.08.2014
comment
В C++ вообще не следует использовать массивы memcpy или C-стиля.   -  person John Dibling    schedule 13.08.2014
comment
Массив указателей на одномерные массивы не является двумерным массивом.   -  person CB Bailey    schedule 13.08.2014
comment
Я сомневаюсь, что вы можете ожидать, что memcpy будет правильно работать с этими complex структурами данных, поскольку они, скорее всего, не являются последовательными в памяти (т. е. они имеют переменные-члены, указывающие на разные области памяти).   -  person barak manos    schedule 13.08.2014
comment
@DevSolar: Спасибо, исправил...   -  person barak manos    schedule 13.08.2014
comment
возможный дубликат C/C++ Как скопировать многомерный массив символов без вложенных циклов?   -  person kiranpradeep    schedule 23.04.2015


Ответы (2)


Вы не используете двумерные массивы. Вы используете одномерные массивы и еще один, в котором хранится набор указателей. Учитывая, что нет гарантии, что ваши массивы будут постоянно находиться в памяти.

Каждый раз, когда вы запрашиваете в коде новое распределение, ваша программа будет находить (новую) область памяти, чтобы соответствовать (новому) массиву. Если вы напечатаете массив, в котором хранятся указатели, вы можете прочитать, где на самом деле находятся ваши массивы.

person cerkiewny    schedule 13.08.2014

Как уже говорилось, вы не должны использовать memcpy здесь.

Но для протокола: когда вы выполняете memcpy таким образом, вы стираете указатели в mat2, создаете утечку и копируете что-то слишком большое в mat2, портя свою память. Правильным способом использования memcpy будет независимое выполнение memcpy для каждой записи mat1 в mat2.

person Community    schedule 13.08.2014