如何使用new在C++中声明一个二维数组?

638

我如何使用 new 声明一个二维数组?

例如,对于“普通”的数组,我会这样做:

int* ary = new int[Size]

但是

int** ary = new int[sizeY][sizeX]

a) 不能工作/编译,b) 也没有实现什么:

int ary[sizeY][sizeX] 

做什么。


74
只有在sizeX是常量时才起作用:int(*ary)[sizeX] = new int[sizeY][sizeX]; 这是创建一个int[sizeY][sizeX]且所有内存都是连续的正确方式。(我认为这不值得回答,因为很可能你的sizeX不是常量。) - Johannes Schaub - litb
36
我很难相信下面所有的答案都是全部错误的,没有回答问题,但它们都得到了赞同。上面Johanes Shaub的评论是唯一正确的回答. 一个二维数组和一个指向数组的指针数组是两个完全不同的东西,显然每个人都混淆了它们。 - Bregalad
8
@JohannesSchaub-litb: 这并不完全正确。当然,在那种情况下它可以工作,但有一种方法可以使所有维度都变化,详见 https://dev59.com/AYnca4cB1Zd3GeqP8UPo#29375830 - Ben Voigt
30个回答

0

我使用了这个不太优雅但是快速、简单且有效的系统。我不明白为什么它不能工作,因为系统允许创建一个大尺寸的数组并访问其部分的唯一方式就是不将其分割成部分:

#define DIM 3
#define WORMS 50000 //gusanos

void halla_centros_V000(double CENW[][DIM])
{
    CENW[i][j]=...
    ...
}


int main()
{
    double *CENW_MEM=new double[WORMS*DIM];
    double (*CENW)[DIM];
    CENW=(double (*)[3]) &CENW_MEM[0];
    halla_centros_V000(CENW);
    delete[] CENW_MEM;
}

0

通过指针定义数组(第1行)开始:

int** a = new int* [x];     //x is the number of rows
for(int i = 0; i < x; i++)
    a[i] = new int[y];     //y is the number of columns

0
如果你想声明一个预定义的指针数组:
int **x;
x = new int*[2] { 
        new int[2] { 0, 1 },
        new int[2] { 2, 3 } 
    };

访问:

cout << x[0][0];

0

我给你留下了一个解决方案,它对于某些情况来说是最好的。尤其是当我们知道数组的一维大小时。对于字符数组非常有用,例如如果我们需要一个大小不同的char [20]数组的数组。

int  size = 1492;
char (*array)[20];

array = new char[size][20];
...
strcpy(array[5], "hola!");
...
delete [] array;

关键是数组声明中的括号。

StackOverflow 只使用英语,请翻译您的问题。 - M. Mimpen

0

如果你只在本地或类内部使用数组,你可以使用lambda表达式创建类似于数组的对象。

int main(int argc, char **argv) {
  srand(time(0));
  int w = rand() % 20 + 10;
  int h = rand() % 20 + 10;
  {
    // Here. Only one line and no memory leak.
    auto arr = [=, p = std::make_unique<int[]>(w * h)](int i, int j) -> int & { return *&p[i * w + j]; };
    arr(1, 0) = 6;
    std::cout << arr(1, 0) << '\n';
  }
}

对象与 int[][] 不兼容,若要将其作为参数传递,您需要使用模板。但这可以避免在访问元素时出现错误的 [i * w + j]
您也可以使用一个裸指针 std::unique_ptr<int[]> 加上实现在 lambda 中的 getter。但是您可能会犯错并产生悬空引用。

0
我还没有足够的声望点来发表评论,但我真的很喜欢@Ben_Voigt在@kamshi的回答中的评论。我花了一些时间来弄清楚如何实施Ben的建议,所以我想贴出代码:
    auto temp = std::make_unique<unsigned int[]>(sizeX * sizeY);
    auto array2d = std::make_unique<unsigned int* []>(sizeX);
    for (unsigned int i = 0; i < sizeY; ++i)
        array2d[i] = (&temp[0] + i * sizeX);

顺便说一下,这是我喜欢这段代码的原因:
我想尽可能多地使用现代C++。
std::array在栈上分配内存,而2D数组的内存是连续分配的,这正是我所需要的。不幸的是,我的数组太大了,无法舒适地放在栈上(大于100kB)。
std::vector在堆上分配内存,这是好的,但是当你像这样分配一个2D向量时:
vector<vector<double>> A(NR, vector<double>(NC, 0.0));

行在内存中不是连续的。我正在使用BLAS(Intel MKL)进行矩阵运算,所以内存必须是连续的。

std::mdspan看起来符合我的需求,但是微软目前还不支持它。

希望对你有帮助。


-1
int **arr = new int* [NoOfRows]
for(int i = 0; i<NoOfRows; i++)
   arr[i] = new int[noOfColumn];

这是使用 new 在 c++ 中声明二维数组的好方法。 这里 NoOfRow 表示您想要多少行, noOfColumn 表示您想要多少列。


这几乎与之前的答案完全相同。 - undefined

-1
我建议使用二维向量而不是二维数组。基本上尽可能多地使用向量,主要是因为:
  1. 动态内存分配无需麻烦
  2. 自动内存管理
以下是一小段代码片段,您可以在其中创建一个动态大小的数组。
vector<vector<int>> arr;
for (int i=0; i<n; i++)
{    
    vector<int> temp;
    for (int j=0; j<k; j++)
    {
        int val;
        //assign values
        temp.push_back(val);
    }
    arr.push_back(temp);
}

-1

动态声明二维数组:

    #include<iostream>
    using namespace std;
    int main()
    {
        int x = 3, y = 3;

        int **ptr = new int *[x];

        for(int i = 0; i<y; i++)
        {
            ptr[i] = new int[y];
        }
        srand(time(0));

        for(int j = 0; j<x; j++)
        {
            for(int k = 0; k<y; k++)
            {
                int a = rand()%10;
                ptr[j][k] = a;
                cout<<ptr[j][k]<<" ";
            }
            cout<<endl;
        }
    }

现在在上面的代码中,我们获取了一个双指针并为其分配了动态内存,并赋予列数值。在这里分配的内存仅用于列,现在对于行,我们只需要使用for循环,并为每一行分配动态内存并分配值。现在我们可以像使用2D数组一样使用指针。在上面的例子中,我们随机分配了数字给我们的2D数组(指针)。这都是关于2D数组的DMA。


-4

我在创建动态数组时使用这个。如果你有一个类或结构体,这个方法也适用。例如:

struct Sprite {
    int x;
};

int main () {
   int num = 50;
   Sprite **spritearray;//a pointer to a pointer to an object from the Sprite class
   spritearray = new Sprite *[num];
   for (int n = 0; n < num; n++) {
       spritearray[n] = new Sprite;
       spritearray->x = n * 3;
  }

   //delete from random position
    for (int n = 0; n < num; n++) {
        if (spritearray[n]->x < 0) {
      delete spritearray[n];
      spritearray[n] = NULL;
        }
    }

   //delete the array
    for (int n = 0; n < num; n++) {
      if (spritearray[n] != NULL){
         delete spritearray[n];
         spritearray[n] = NULL;
      }
    }
    delete []spritearray;
    spritearray = NULL;

   return 0;
  } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接