我不是在寻找解决方案,我在Google上找到了很多。我正在寻找解释。
在玩数组时,我发现动态声明2D数组并不像预期的那样工作
1D数组,工作
int main()
{
int rows;
int* pointer;
pointer = new int[rows];
}
2D数组,不起作用
int main()
{
int rows;
int columns;
int* pointer;
pointer = new int[rows][columns]; //error on this line
}
在我看来,这就像直观的做事方式,因为它是如何用常规数组完成的,但显然它是不正确的,不会编译。
我无法找到明确解释为什么会出现这种情况,希望有人能够启发我。
谢谢:)
答案 0 :(得分:6)
这不起作用的原因是因为能够拥有一个二维数组,你需要一个指针数组,它将指向你想要的许多类型的数组。
在这种情况下,您尝试将地址存储到int *数组中(其中每个“单元格”将指向一个int的数组)在int *类型的变量中,它应该是int **。
回顾一下: 1D数组:int * 2D数组:int ** 3D数组:int ***
所有数组必须是一维的原因是因为你的内存是一维的(将所有内存都视为一个大的内存地址数组),这意味着多维数组必须“伪造”。
答案 1 :(得分:4)
这不仅是其他答案所描述的数据类型问题。
像
这样的语法pointer = new int[rows][columns]
仅在columns
是常量表达式时有效。你不能在那里使用变量(但请注意rows
可以是变量)。
这是解释。 C ++标准使您能够以下列方式使用new
运算符的二维数组语法(来自§5.3.4/ 1):
new-expression:
::opt new new-placementopt new-type-id new-initializeropt
::opt new new-placementopt ( type-id ) new-initializeropt
new-placement:
( expression-list )
new-type-id:
type-specifier-seq new-declaratoropt
new-declarator:
ptr-operator new-declaratoropt
noptr-new-declarator
noptr-new-declarator:
[ expression ] attribute-specifier-seqopt
noptr-new-declarator [ constant-expression ] attribute-specifier-seqopt
new-initializer:
( expression-listopt )
braced-init-list
相关部分是:
noptr-new-declarator:
[ expression ] attribute-specifier-seqopt
noptr-new-declarator [ constant-expression ] attribute-specifier-seqopt
第一行表示您可以在type-id后面加上一个括号表达式。第二行(这是一个递归语句)允许您在初始行之后使用多对括号,但它们必须包含常量表达式。
标准进一步解释了这一点(强调我的):
(§5.3.4/ 5)当分配的对象是一个数组(即使用noptr-new-declarator语法或new-type-id或type-id表示数组类型)时,新的-expression产生一个指向数组初始元素(如果有)的指针。 [注意:new int和new int [10]都有int *类型,new int [i] [10]的类型是int(*)[10] - end note]属性 - noptr-new-declarator中的specifier-seq属于相关的数组类型。
(§5.3.4/ 6)noptr-new-declarator中的每个常量表达式都应是一个整数常量表达式(5.19)并计算为严格正值。 noptr-new-declarator中的表达式应该是整数类型,unscoped枚举类型,或者是存在单个非显式转换函数到整数或未整数枚举类型的类类型(12.3)。 [...] [示例:给定int n = 42的定义,new float [n] [5]格式正确(因为n是noptr-new-declarator的表达式),但是new float [ 5] [n]格式不正确(因为n不是常数表达式)。 - 结束例子]
答案 2 :(得分:3)
你可以通过以下方式理解它:
2-D数组看起来像一个带有行和列的网格,用于人类表示但在内存中它存储在连续的内存中。因此,无论何时说出二维数组或大小mxn
,您都在谈论m
个n
元素数组,每个元素都依次存储。即对于3x3网格元素存储为:
(0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)
如果要访问此类数据结构,则需要使用指向指针的指针,即指向每行第一个元素的位置地址数组的指针。
因此可以通过3(行数)地址访问数组
(Address of element 0,1) (Address of element 1,0) (Address of element 2,0)
由于存储了元素的地址,所以现在需要一个指向指针的指针来访问这个指针数组(保存每行第一个元素的地址)。
对于1D阵列:
int* pointer = new int[3];
Array: (0) (1) (2)
pointer: (Address of first element of Array)
对于2D数组:
int **pointer = new int[3][3];
Array: (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)
Row Address Array: (Address of 0,1) (Address of 1,0) (Address of 2,0)
pointer: (Address of first element of Row Address Array)
希望这有帮助!
答案 3 :(得分:0)
其他人已经很好地解释了这一点,但是这里有一个例子可以阐明使用new
创建动态大小的多维数组:
int rows = 20;
int columns = 30;
// the following is essentially just an array of int pointers
int **pointer = new int*[rows];
// so, loop through the array creating the second dimension
for (int i = 0;i < rows;i++)
pointer[i] = new int[columns];
答案 4 :(得分:0)
这是一维字符指针数组:char* Dynamic_One_Dimensional_Char_Pointer_Array
。请注意char *
。
这是一个二维字符指针数组:char **Dynamic_Two_Dimensional_Char_Pointer_Array
。请注意char **
。
这是为二维char指针数组分配内存的方法:
//memory allocated for elements of rows.
Dynamic_Two_Dimensional_Char_Pointer_Array = new char *[ROWS] ;
//memory allocated for elements of each column.
for( i = 0 ; i < ROWS ; i++ ) Dynamic_Two_Dimensional_Char_Pointer_Array[i] = new char[COLUMNS];
这是打印2D数组([rows][columns]
)的方法:
for(rows=0;rows<maxLines;rows++)
{
for(int columns=0;columns<strlen(Dynamic_Two_Dimensional_Char_Pointer_Array[rows]);columns++)
{
cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows][columns]<<"";
}
cout<<" \n";
}
他是如何为二维字符指针数组解除内存的分配:
//free the allocated memory
for( i = 0 ; i < ROWS ; i++ ) delete [] Dynamic_Two_Dimensional_Char_Pointer_Array[i] ;
delete [] Dynamic_Two_Dimensional_Char_Pointer_Array ;
完整的示例代码:
#include<vector>
#include<string>
#include<iostream>
using namespace std;
int main()
{
int COLUMNS =80; //80 characters wide
int ROWS =20;// 20 lines
int i,maxLines=0;
char* Dynamic_One_Dimensional_Char_Pointer_Array = new char[80];
char **Dynamic_Two_Dimensional_Char_Pointer_Array = 0;
//memory allocated for elements of rows.
Dynamic_Two_Dimensional_Char_Pointer_Array = new char *[ROWS] ;
//memory allocated for elements of each column.
for( i = 0 ; i < ROWS ; i++ ) Dynamic_Two_Dimensional_Char_Pointer_Array[i] = new char[COLUMNS];
strcpy(Dynamic_One_Dimensional_Char_Pointer_Array,"apples 123 oranges 456 bananas 789 lemons 101112 kiwi 132415 grapes 161718" );
cout<<" \ninput = "<<Dynamic_One_Dimensional_Char_Pointer_Array<<" \n\n";
cout<<"Output = \n";
char seperators[] = " ,\t\n";
char *token;
token = strtok( Dynamic_One_Dimensional_Char_Pointer_Array, seperators );
i=0;
while( token != NULL )
{
strcpy(Dynamic_Two_Dimensional_Char_Pointer_Array[i],token);
token = strtok( NULL, seperators );
i++;
}
maxLines=i;
cout<<" \n";
cout<<"show contents 1 print [rows] \n";
cout<<"-------------------------------------------\n";
for(int rows=0;rows<maxLines;rows++)
{
cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows]<<" \n";
}
cout<<" \n";
cout<<"show contents 2 print [rows][columns]\n";
cout<<"-------------------------------------------\n";
for(rows=0;rows<maxLines;rows++)
{
//cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows]<<" \n";
for(int columns=0;columns<strlen(Dynamic_Two_Dimensional_Char_Pointer_Array[rows]);columns++)
{
cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows][columns]<<"";
}
cout<<" \n";
}
delete[] Dynamic_One_Dimensional_Char_Pointer_Array;
//free the allocated memory
for( i = 0 ; i < ROWS ; i++ ) delete [] Dynamic_Two_Dimensional_Char_Pointer_Array[i] ;
delete [] Dynamic_Two_Dimensional_Char_Pointer_Array ;
return 0;
}