C++ C++;3d阵列-动态内存分配在一行中对齐

C++ C++;3d阵列-动态内存分配在一行中对齐,c++,c,arrays,memory,allocation,C++,C,Arrays,Memory,Allocation,我有一个很奇怪的问题,可能没有实际用途,但答案让我很困扰。今天我试着用下面的代码来处理数组以及它们在内存中的分配:(编译器Xcode 4 btw,4字节整数) int***c; int size_x=0; int size_y=0; int size_z=0; cout size_x; cout size_y; cout size_z; c=新的整数**[大小x]; 对于(int i=0;i和 Dele[]。若要分配数组,最好直接使用向量;)每个新建[]都需要删除[]。非常感谢您的回答。有很多意

我有一个很奇怪的问题,可能没有实际用途,但答案让我很困扰。今天我试着用下面的代码来处理数组以及它们在内存中的分配:(编译器Xcode 4 btw,4字节整数)

int***c;
int size_x=0;
int size_y=0;
int size_z=0;
cout size_x;
cout size_y;
cout size_z;
c=新的整数**[大小x];
对于(int i=0;icout是的,这是正常的。内存是对齐的,顺便说一句,它只是不连续的,因为后续调用
new
不能保证这一点。是的,您可以在单个连续缓冲区中分配整个三维数组:

int *A = new int[size_x * size_y * size_z];
或者,更安全

std::vector<int> A(size_x * size_y * size_z);
获取
(i,j,k)
处的元素

这实际上是非常有用的,因为它给了你多维数组,开销小,保存和防止间接。而且,这种分配方案的错误处理要简单得多,这样你就不会有内存泄漏的风险。任何好的矩阵库都会以这种方式实现。对于C++,包括:


关于解除分配:是的,在当前方案中需要多次调用<代码>删除[]/COD>。< P> >问题不是你的内存不对齐……C++命令要求调用<代码>新< /COD>和<代码> NeX[]

是指它传回一个指针,指向与平台和请求对象大小正确对齐的连续内存

您的问题是,对
new[]
的一次调用并不是为数组分配整个缓冲区,而是多次调用
new[]
。因此,虽然每次调用
new
都将返回对齐的连续内存,但对
new[]的多次调用
不需要返回自己连续分配的内存缓冲区。例如,每次调用
new[]
都会返回对齐的内存,但正如您所指出的,在
new
返回的每个内存数组的开头都可能有“间隙”。这些“间隙”的原因是什么可能有多种原因,这实际上取决于底层操作系统如何为您的程序分配内存

如果不希望每个数组中都有任何“间隙”,则需要通过调用
new
来分配整个缓冲区

最后,要回答您关于
delete[]
的问题,是的,因为您没有通过对
new[]
的一次调用来分配整个内存缓冲区,您不能通过对
delete[]
的一次调用来删除数组。对
new[]
的每次调用都必须与对
delete[]的调用配对
因为这些是单独的内存分配。

是的,这是正常的。
您可以逐行分配数据;唯一可以确定的是数据在每一行上都是连续的。

因为这是标记为C的,所以这里还有一个C答案。因为C99多维数组可以非常有效地处理,即使大小是动态的:

double c[size_x][size_y][size_z];
这会在堆栈上连续分配矩阵。矩阵元素由
c[i][j][k]
访问,编译器会为您执行所有索引算法。如果您担心这会导致这种情况,您可以使用它轻松调用
malloc

double (*c)[size_y][size_z] = malloc(sizeof(double[size_x][size_y][size_z]));

下面是一个例程,它在连续内存空间中分配尺寸为N1 x N2 x N3的3D数组,同时允许您使用a[i][j][k]语法进行运算符访问。该数组是动态的,但连续的,因此它比向量方法和新[]调用循环有巨大的优势

template <class T> T ***Create3D(int N1, int N2, int N3)
{
    T *** array = new T ** [N1];

    array[0] = new T * [N1*N2];

    array[0][0] = new T [N1*N2*N3];

    int i,j,k;

    for( i = 0; i < N1; i++) {

        if (i < N1 -1 ) {

            array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);

            array[i+1] = &(array[0][(i+1)*N2]);

        }

        for( j = 0; j < N2; j++) {     
            if (j > 0) array[i][j] = array[i][j-1] + N3;
        }

    }

    cout << endl;
    return array;
};

template <class T> void Delete3D(T ***array) {
    delete[] array[0][0]; 
    delete[] array[0];
    delete[] array;
};

我添加了一个C++标签。我是否应该删除C标签,或者你真的想要有一个C答案吗?Mon DealC++和C++在实现多维数组方面有很大的不同。这实际上是一个实际的使用,通过移除间接和帮助缓存。顺便说一句,而不是使用<代码> NeX[]/Calp>和<代码> Dele[]。若要分配数组,最好直接使用
向量
;)每个
新建[]
都需要
删除[]
。非常感谢您的回答。有很多意义,并为我清除了问题。。我现在写了上面的内容,我是如何删除内存的。它似乎工作正常。当我在使用相同的空间后分配内存时,不要在最后一行中执行
delete[]m\u数组,m_array=NULL;
在最后一行中……逗号不会创建“序列点”根据C++的规范,因此取决于编译器是如何决定对操作进行排序的,当编译器决定反转操作并将<代码> null >代码>分配到MyLoad,然后调用<代码> Dele[]时,可能会导致巨大的内存泄漏。在now
NULL
指针上。你会想用分号分隔这两个单独的语句。第一个语句也更快吗?我可以想象,因为系统不需要如此频繁地跳转,对吗?@MarkusPfundstein:对于许多操作,是的。这就是我所说的引用位置。这也是等价的nt到上面larsman的答案,其中数组被分配为
int*A=new int[N1*N2*N3]
,被访问为
val=A[i*N2*N3+j*N3+k]
。但这里是指向指针的所有指针的bc,您可以使用
val=array3d[i][j][k]
。要获得数组的等效
int*
类型引用,可以执行
int*A=array3d[0][0]
double c[size_x][size_y][size_z];
double (*c)[size_y][size_z] = malloc(sizeof(double[size_x][size_y][size_z]));
template <class T> T ***Create3D(int N1, int N2, int N3)
{
    T *** array = new T ** [N1];

    array[0] = new T * [N1*N2];

    array[0][0] = new T [N1*N2*N3];

    int i,j,k;

    for( i = 0; i < N1; i++) {

        if (i < N1 -1 ) {

            array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);

            array[i+1] = &(array[0][(i+1)*N2]);

        }

        for( j = 0; j < N2; j++) {     
            if (j > 0) array[i][j] = array[i][j-1] + N3;
        }

    }

    cout << endl;
    return array;
};

template <class T> void Delete3D(T ***array) {
    delete[] array[0][0]; 
    delete[] array[0];
    delete[] array;
};
int *** array3d;
int N1=4, N2=3, N3=2;

int elementNumber = 0;

array3d = Create3D<int>(N1,N2,N3);

cout << "{" << endl;
for (i=0; i<N1; i++) {
    cout << "{";
    for (j=0; j<N2; j++) {
        cout << "{";
        for (k=0; k<N3; k++) {
            array3d[i][j][k] = elementNumber++;
            cout << setw(4) << array3d[i][j][k] << " ";
        }
        cout << "}";
    }
    cout << "}";
    cout << endl ;
}
cout << "}" << endl;

Delete3D(array3d);
{
{{   0    1 }{   2    3 }{   4    5 }}
{{   6    7 }{   8    9 }{  10   11 }}
{{  12   13 }{  14   15 }{  16   17 }}
{{  18   19 }{  20   21 }{  22   23 }}
}