4

我不是在这里寻找解决方案,我在 Google 上找到了很多。我正在寻找解释。

在玩数组时,我发现动态声明 2D 数组不像预期的那样工作

一维阵列,作品

int main()
{
int rows;
int* pointer;
pointer = new int[rows]; 
}

二维数组,不起作用

int main()
{
int rows;
int columns;
int* pointer;
pointer = new int[rows][columns]; //error on this line
}

在我看来,这似乎是一种直观的做事方式,因为这就是它使用常规数组的方式,但显然它不正确并且不会编译。

我一直无法找到一个明确的解释为什么会这样,希望这里有人能启发我。

谢谢 :)

4

5 回答 5

6

这不起作用的原因是因为能够拥有一个二维数组,您需要一个指针数组,它将指向许多您想要的类型的数组。

在这种情况下,您尝试将地址存储到 int* 数组(其中每个“单元格”将指向一个 int 数组)在 int* 类型的变量中,它应该是 int**。

回顾一下: 1D 数组:int* 2D 数组:int** 3D 数组:int***

所有数组必须是一维的原因是因为您的内存是一维的(将所有内存视为一个大内存地址数组),这意味着必须“伪造”多维数组。

于 2012-09-13T05:03:11.043 回答
4

这不仅是其他答案所描述的数据类型的问题。

像这样的语法

pointer = new int[rows][columns]

仅当columns是常量表达式时才有效。您不能在那里使用变量(但请注意,它rows可以是变量)。

这是解释。newC++ 标准允许您仅通过以下方式将二维数组语法与运算符一起使用(来自 §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 表示数组类型)时,new-expression 产生指向数组初始元素(如果有)的指针。[注意:new int 和 new int[10] 都具有 int* 类型,并且 new int[i][10] 的类型是 int (*)[10] — end note ] noptr-中的属性说明符序列new-declarator 属于关联的数组类型。

(§5.3.4/6) noptr-new-declarator 中的每个常量表达式都应是一个整数常量表达式 (5.19),并计算为严格的正值。noptr-new-declarator 中的表达式应为整数类型、无范围枚举类型或存在单个非显式转换函数到整数或无范围枚举类型的类类型 (12.3)。[...] [ 示例:给定定义 int n = 42,new float[n][5] 是格式良好的(因为 n 是 noptr-new-declarator 的表达式),但是 new float[5][ n] 格式不正确(因为 n 不是常量表达式)。—结束示例]

于 2012-09-13T05:15:59.047 回答
3

那么你可以通过以下方式理解它:

二维数组看起来像一个带有行和列的网格,用于人类表示,但在内存中它存储在连续的内存中。因此,每当您说二维数组或大小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)

由于存储了元素的地址,所以现在您需要一个指向指针的指针来访问这个指针数组(保存每行第一个元素的地址)。

对于一维数组:

int* pointer = new int[3];

Array: (0) (1) (2)
pointer: (Address of first element of Array)

对于二维数组:

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)

希望这可以帮助!

于 2012-09-13T05:00:48.383 回答
0

这是一个一维字符指针数组:char* Dynamic_One_Dimensional_Char_Pointer_Array。注意char *.

这是一个二维字符指针数组:char **Dynamic_Two_Dimensional_Char_Pointer_Array。注意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];

这是如何打印二维数组 ( [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;
}
于 2012-09-13T05:58:58.340 回答
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];
于 2012-09-13T05:13:03.520 回答