多维动态数组,为什么不起作用?

时间:2012-09-13 04:56:44

标签: c++ arrays pointers

我不是在寻找解决方案,我在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
}

在我看来,这就像直观的做事方式,因为它是如何用常规数组完成的,但显然它是不正确的,不会编译。

我无法找到明确解释为什么会出现这种情况,希望有人能够启发我。

谢谢:)

5 个答案:

答案 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,您都在谈论mn元素数组,每个元素都依次存储。即对于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;
}