为什么不能在C ++中使用一个新调用分配多维数组?

时间:2010-10-24 16:36:47

标签: c++ standards

在C ++中,您可以轻松地分配一维数组:

T *array=new T[N];

你也可以用一个语句删除它:

delete[] array;

编译器将知道如何解除分配正确的字节数的魔力。

但为什么不能像这样分配二维数组?

T *array=new T[N,M];

或者甚至喜欢这个?

T *array=new T[N,M,L];

如果你想要一个多维,你必须这样做:

T **array=new T*[N];
for(int i=0;i<N;i++) array[i]=new T[M];

如果你想要一个使用矩阵的快速程序(矩阵运算,特征值算法等等),你可能也希望利用缓存来获得最佳性能,这需要数据在同一个地方。使用vector<vector<T> >是相同的情况。在C中,您可以在堆栈上使用可变长度数组,但是您无法在堆上分配它们(并且堆栈空间非常有限),您也可以在C ++中执行可变长度数组,但它们不会出现在C中++ 0x中。

唯一的解决方法是相当hackish和错误 -

T *array=new T[N*M];
for(int i=0;i<N;i++)
   for(int j=0;j<M;j++)
   {
       T[i*N+j]=...;
   }

8 个答案:

答案 0 :(得分:8)

执行T *array=new T[N*M];的方法是最接近真正的多维数组。请注意,要找到此数组中的元素,您需要M的值(我相信您的示例是错误的,它应该是T[i*M+j]),这只在运行时才知道。

在编译时分配2D数组时,比如array[5][10],值10是一个常量,因此编译器只需生成用于计算i*10+j的代码。但是,如果您执行new T[N,M],则表达式i*M+j取决于分配数组时M的值。编译器需要一些方法来存储M的值以及实际的数组本身,事情只会从这里变得混乱。我想这就是为什么他们决定不在语言中包含这样的功能。

至于你的解决方法,你可以通过编写一个重载operator ()的包装类来减少“hackish”,这样你就可以做array(i, j) = ...之类的事情。

答案 1 :(得分:3)

因为多维数组与数组/指针数组不同。

答案 2 :(得分:1)

使用std :: vector

答案 3 :(得分:1)

  

为什么不能在C ++中使用一个新调用分配多维数组?

因为当ISO编写C ++语言标准时,他们并没有决定将该功能添加到该语言中。我不知道为什么他们决定不这样做。

如果您不喜欢,可以创建辅助函数来分配/释放多维数组,或者可以切换到支持轻松分配多维数组的C#或Java等语言。

答案 4 :(得分:0)

然而,您可以做的是从堆中分配包含二维数组的对象。我只想为它编写一个包装类。

答案 5 :(得分:0)

昨晚我正在考虑这个问题,这个解决方案来找我。

T * raw = new T[N*M];
T ** array = new T*[N];

for(int i=0; i<N; i++)
    array[i] = raw + i * M;

现在“数组”的行为就像一个连续的静态大小的二维数组。您只需要删除原始数组和多维数组。

答案 6 :(得分:0)

我建议您使用同名库中的Boost::multi_array,它提供了一个多维数组的简单接口。它可以在一行中分配,并且在足够高的优化级别通常与本机阵列一样快。

以下是图书馆网站的一些示例代码:

#include "boost/multi_array.hpp"
#include <cassert>

int 
main () {
  // Create a 3D array that is 3 x 4 x 2
  typedef boost::multi_array<double, 3> array_type;
  typedef array_type::index index;
  array_type A(boost::extents[3][4][2]);

  // Assign values to the elements
  int values = 0;
  for(index i = 0; i != 3; ++i) 
    for(index j = 0; j != 4; ++j)
      for(index k = 0; k != 2; ++k)
        A[i][j][k] = values++;

  // Verify values
  int verify = 0;
  for(index i = 0; i != 3; ++i) 
    for(index j = 0; j != 4; ++j)
      for(index k = 0; k != 2; ++k)
        assert(A[i][j][k] == verify++);

  return 0;
}

答案 7 :(得分:-1)

因为逗号是操作符。

int a = (3, 5, 7, 9);

程序将评估3,丢弃结果, 评价5,丢弃结果, 评估7,丢弃结果, 评估9,并将其分配给。

因此,您正在寻找的语法无法使用, 并保留向后兼容c。