我如何声明一个2d数组使用新?

比如,对于一个“普通”数组,我将:

int* ary = new int[Size]

but

int** ary = new int[sizeY][sizeX]

A)不工作/编译b)没有完成什么:

int ary[sizeY][sizeX] 

所做的事。


当前回答

int** ary = new int[sizeY][sizeX]

应该是:

int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
    ary[i] = new int[sizeX];
}

然后清理是:

for(int i = 0; i < sizeY; ++i) {
    delete [] ary[i];
}
delete [] ary;

编辑:正如Dietrich Epp在评论中指出的那样,这并不是一个轻量级的解决方案。另一种方法是使用一个大内存块:

int *ary = new int[sizeX*sizeY];

// ary[i][j] is then rewritten as
ary[i*sizeY+j]

其他回答

如果你的项目是CLI(公共语言运行时支持),那么:

你可以使用数组类,而不是你写的那个:

#include <array>
using namespace std;

换句话说,不是使用std名称空间和包含数组头时获得的非托管数组类,不是std名称空间和数组头中定义的非托管数组类,而是CLI的托管类数组。

使用这个类,您可以创建任意级别的数组。

下面的代码创建了一个2行3列的二维数组,类型为int,并命名为“arr”:

array<int, 2>^ arr = gcnew array<int, 2>(2, 3);

现在您可以访问数组中的元素,通过命名它并只写一个平方括号[],并在其中添加行和列,并用逗号分隔它们。

下面的代码访问我已经在上面的代码中创建的数组的第2行和第1列中的一个元素:

arr[0, 1]

只写这一行是为了读取该单元格中的值,即获取该单元格中的值,但如果添加等号,则要写入该单元格中的值,即设置该单元格中的值。 当然,你也可以使用+=,-=,*=和/=运算符,仅用于数字(int, float, double, __int16, __int32, __int64等),但你肯定已经知道了。

如果您的项目不是CLI,那么您可以使用std名称空间的非托管数组类,当然,如果您使用#include <array>,但是问题是这个数组类与CLI数组不同。创建这种类型的数组与CLI相同,除了必须删除^符号和gcnew关键字。但不幸的是,<>括号中的第二个int参数指定了数组的长度(即大小),而不是它的秩!

没有办法在这类数组中指定rank, rank是CLI数组的特性。

STD数组的行为类似于c++中的普通数组,使用指针定义,例如int*,然后:new int[size],或者不使用指针:int arr[size],但与c++中的普通数组不同,STD数组提供了可以与数组元素一起使用的函数,如fill, begin, end, size等,但普通数组什么也没有提供。

但是std数组仍然是一维数组,就像普通的c++数组一样。 但是多亏了其他人提出的关于如何将普通的c++一维数组转换为二维数组的解决方案,我们可以将同样的想法应用到std数组中,例如,根据Mehrdad Afshari的想法,我们可以编写以下代码:

array<array<int, 3>, 2> array2d = array<array<int, 3>, 2>();

这一行代码创建了一个“罐子数组”,这是一个一维数组,它的每个单元格都是或指向另一个一维数组。

如果一维数组中所有一维数组的长度/大小都相等,那么你可以将array2d变量视为一个真正的二维数组,另外你可以使用特殊的方法来处理行或列,这取决于你如何看待它,在二维数组中,std数组支持。

你也可以使用Kevin Loney的解决方案:

int *ary = new int[sizeX*sizeY];

// ary[i][j] is then rewritten as
ary[i*sizeY+j]

但如果你使用STD数组,代码必须看起来不同:

array<int, sizeX*sizeY> ary = array<int, sizeX*sizeY>();
ary.at(i*sizeY+j);

并且仍然具有std数组的独特功能。

请注意,您仍然可以使用[]括号访问std数组的元素,并且不必调用at函数。 您还可以定义并赋值一个新的int变量,该变量将计算并保持std数组中元素的总数,并使用它的值,而不是重复sizeX* sizeey

You can define your own two dimensional array generic class, and define the constructor of the two dimensional array class to receive two integers to specify the number of rows and columns in the new two dimensional array, and define get function that receive two parameters of integer that access an element in the two dimensional array and returns its value, and set function that receives three parameters, that the two first are integers that specify the row and column in the two dimensional array, and the third parameter is the new value of the element. Its type depends on the type you chose in the generic class.

你将能够通过使用普通的c++数组(指针或不指针)或std数组来实现所有这些,并使用其他人建议的想法之一,并使其易于使用,如cli数组,或像你可以在c#中定义、赋值和使用的二维数组。

试着这样做:

int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
    ary[i] = new int[sizeX];

我建议使用2D向量而不是2D数组。基本上尽可能使用向量主要是因为

动态内存分配没有麻烦 自动内存管理

下面是一个小代码片段,您可以在其中创建一个动态大小的数组

vector<vector<int>> arr;
for (int i=0; i<n; i++)
{    
    vector<int> temp;
    for (int j=0; j<k; j++)
    {
        int val;
        //assign values
        temp.push_back(val);
    }
    arr.push_back(temp);
}

这个答案的目的不是添加其他答案没有涵盖的新内容,而是扩展@Kevin Loney的答案。

你可以使用轻量级声明:

int *ary = new int[SizeX*SizeY]

访问语法将是:

ary[i*SizeY+j]     // ary[i][j]

但这对大多数人来说都很麻烦,可能会导致混乱。所以,你可以这样定义宏:

#define ary(i, j)   ary[(i)*SizeY + (j)]

现在可以使用非常相似的语法ary(i, j) //表示ary[i][j]。 这具有简单美观的优点,同时,使用表达式代替索引也更简单,不那么令人困惑。

要访问,比如说,ary[2+5][3+8],你可以写ary(2+ 5,3 +8),而不是看起来复杂的ary[(2+5)*SizeY +(3+8)],也就是说,它节省了括号,有助于可读性。

警告:

尽管语法非常相似,但并不相同。 如果将数组传递给其他函数,则必须以相同的名称传递SizeY(或者声明为全局变量)。

或者,如果你需要在多个函数中使用数组,那么你可以在宏定义中添加SizeY作为另一个参数,如下所示:

#define ary(i, j, SizeY)  ary[(i)*(SizeY)+(j)]

你懂的。当然,这会变得太长而没有用处,但它仍然可以防止+和*的混淆。

当然不推荐这样做,大多数有经验的用户会谴责这是一种糟糕的做法,但我还是忍不住要分享它,因为它很优雅。

编辑: 如果你想要一个适用于任意数量数组的可移植解决方案,你可以使用以下语法:

#define access(ar, i, j, SizeY) ar[(i)*(SizeY)+(j)]

然后你可以使用访问语法将任意大小的数组传递给调用:

access(ary, i, j, SizeY)      // ary[i][j]

附注:我已经测试了这些,在g++14和g++11编译器上可以使用相同的语法(作为左值和右值)。

Typedef是你的朋友

在回顾并查看了许多其他答案之后,我发现需要进行更深层次的解释,因为许多其他答案要么存在性能问题,要么迫使您使用不寻常的或繁重的语法来声明数组,或访问数组元素(或以上所有问题)。

首先,这个答案假设您在编译时知道数组的尺寸。如果你这样做,那么这是最好的解决方案,因为它将提供最好的性能,并允许您使用标准数组语法来访问数组元素。

The reason this gives the best performance is because it allocates all of the arrays as a contiguous block of memory meaning that you are likely to have less page misses and better spacial locality. Allocating in a loop may cause the individual arrays to end up scattered on multiple non-contiguous pages through the virtual memory space as the allocation loop could be interrupted ( possibly multiple times ) by other threads or processes, or simply due to the discretion of the allocator filling in small, empty memory blocks it happens to have available.

其他好处是声明语法简单,数组访问语法标准。

在c++中使用new:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (array5k_t)[5000];

array5k_t *array5k = new array5k_t[5000];

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

或使用calloc的C样式:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}