我如何使用 new 声明一个二维数组?
例如,对于“普通”的数组,我会这样做:
int* ary = new int[Size]
但是
int** ary = new int[sizeY][sizeX]
a) 不能工作/编译,b) 也没有实现什么:
int ary[sizeY][sizeX]
做什么。
我如何使用 new 声明一个二维数组?
例如,对于“普通”的数组,我会这样做:
int* ary = new int[Size]
但是
int** ary = new int[sizeY][sizeX]
a) 不能工作/编译,b) 也没有实现什么:
int ary[sizeY][sizeX]
做什么。
如何在GNU C++中分配连续的多维数组?有一个GNU扩展可以使“标准”语法起作用。
似乎问题来自于 operator new []。请确保使用 operator new :
double (* in)[n][n] = new (double[m][n][n]); // GNU extension
这就是全部:你将获得一个与C兼容的多维数组...
double (*in)[m][n] = (double (*)[m][n])new double[k*m*n];
这个也不行。我在 n
上得到了 C2057、C2540 错误,因为它在编译时是未知的。我不明白为什么不能这样做,因为内存已经正确分配了,而且只是用指针方便地处理这个内存。(VS 2010) - user1234567gcc
让我产生了困惑:只使用-std=c++11
并不足以开启严格的标准一致性,还需要使用-pedantic-errors
。如果没有后面的标志,即使强制类型转换确实不符合C++标准,gcc
也会轻松接受它。根据我现在所知,我只能建议在进行大量依赖于多维数组的操作时退回到C语言。 C99在这方面比甚至C++17更为强大。 - cmaster - reinstate monicatypedef可以提高代码可读性。
回顾其他答案后,需要对此进行更深入的解释。因为其他答案要么存在性能问题,要么需要使用不常见或繁琐的语法来声明数组或访问数组元素(或者包括以上所有问题)。
首先,本答案假定您在编译时知道数组的维度。如果是这样,那么这是最佳解决方案,因为它既可以给出最佳性能,又允许您使用标准数组语法来访问数组元素。
之所以能够提供最佳性能,是因为它将所有数组分配为相邻的内存块,这意味着您可能会有更少的页面错误和更好的空间局部性。在循环中分配可能导致单个数组散布在虚拟内存空间的多个非相邻页面上,因为分配循环可能会被其他线程或进程打断(可能是多次),或者仅仅是由于分配器填充其可用的小型空闲内存块的裁量权而出现这种情况。
其他好处是简单的声明语法和标准的数组访问语法。
在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;
}
或者使用 C 语言的 calloc 函数:
#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;
}
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)*SizeY + (3+8)]
,这样可以节省括号并提高可读性。
注意事项:
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编译器中都可以作为左值和右值使用。
尝试执行以下操作:
int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
ary[i] = new int[sizeX];
这里有两种选项。第一种显示了数组的概念,或者指针的概念。我更喜欢第二种,因为地址是连续的,就像您在图像中看到的那样。
#include <iostream>
using namespace std;
int main(){
int **arr_01,**arr_02,i,j,rows=4,cols=5;
//Implementation 1
arr_01=new int*[rows];
for(int i=0;i<rows;i++)
arr_01[i]=new int[cols];
for(i=0;i<rows;i++){
for(j=0;j<cols;j++)
cout << arr_01[i]+j << " " ;
cout << endl;
}
for(int i=0;i<rows;i++)
delete[] arr_01[i];
delete[] arr_01;
cout << endl;
//Implementation 2
arr_02=new int*[rows];
arr_02[0]=new int[rows*cols];
for(int i=1;i<rows;i++)
arr_02[i]=arr_02[0]+cols*i;
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++)
cout << arr_02[i]+j << " " ;
cout << endl;
}
delete[] arr_02[0];
delete[] arr_02;
return 0;
}
int main(void)
{
double **a2d = new double*[5];
/* initializing Number of rows, in this case 5 rows) */
for (int i = 0; i < 5; i++)
{
a2d[i] = new double[3]; /* initializing Number of columns, in this case 3 columns */
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
a2d[i][j] = 1; /* Assigning value 1 to all elements */
}
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a2d[i][j] << endl; /* Printing all elements to verify all elements have been correctly assigned or not */
}
}
for (int i = 0; i < 5; i++)
delete[] a2d[i];
delete[] a2d;
return 0;
}
这是一个旧的答案,但我喜欢用以下方式声明C++动态数组
int sizeY,sizeX = 10;
//declaring dynamic 2d array:
int **ary = new int*[sizeY];
for (int i = 0; i < sizeY; i++)
{
ary[i] = new int[sizeX];
}
#include <array>
using namespace std;
array<int, 2>^ arr = gcnew array<int, 2>(2, 3);
arr[0, 1]
只写这一行是为了读取那个单元格的值,即获取此单元格中的值,但如果添加等于号=
,则将要在该单元格中写入值,即设置此单元格中的值。
当然,您也可以使用+=、-=、*=和/=运算符,仅适用于数字(int、float、double、__int16、__int32、__int64等),但您肯定已经知道了。
如果您的项目不是CLI,则可以使用std命名空间的非托管数组类,当然,如果您#include <array>
。但问题是,此数组类与CLI数组不同。创建此类型的数组与CLI相同,除了您必须删除^
符号和gcnew
关键字。但不幸的是<>
括号中的第二个int参数指定了数组的长度(即大小),而不是其秩!
在这种类型的数组中没有办法指定秩,秩是CLI数组的特性而已。
在C++中,std数组的行为类似于普通数组,您可以使用指针定义,例如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>();
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*sizeY
您可以定义自己的二维数组通用类,并将二维数组类的构造函数定义为接收两个整数以指定新二维数组中的行数和列数,并定义get函数,该函数接收两个整数参数来访问二维数组中的元素并返回其值,以及set函数,它接收三个参数,前两个是指定二维数组中的行和列的整数,第三个参数是元素的新值。其类型取决于您在通用类中选择的类型。
您将能够通过使用普通的c++数组(指针或无指针)或std数组之一,并使用其他人建议的其中一个想法之一来实现所有这些,并使其易于像cli数组那样使用,或者像C#中定义,分配和使用的二维数组。
int** mat = new int*[n];
mat[0] = new int [n * n];
然而,由于上面的分配是线性的,删除如下:
delete [] mat[0];
delete [] mat;
int (*intPtr)[n] = new int[x][n]
int (*intPtr)[8] = new int[75][8];
intPtr[5][5] = 6;
cout<<intPtr[0][45]<<endl;