如何在C++中创建给定大小的二维数组

How to create a two dimensional array of given size in C++

本文关键字:二维数组 创建 C++      更新时间:2023-10-16

我需要创建一个给定大小的方阵。我知道如何创建给定大小的动态一维数组。对于像下面几行这样的两个二元数组不是同样有效吗?

cin>>size;
int* a[][]=new int[size][size]
int* a[][]=new int[size][size]

,这行不通。

main.cpp:4: error: only the first dimension of an allocated array may have dynamic size
    new int[size][size];
                  ^~~~

如果行的大小是固定的,那么您可以执行以下操作:

// allocate an array with `size` rows and 10 columns
int (*array)[10] = new int[size][10];

在C++中,您不能拥有两个维度的原始数组,其中两个维度都是动态的。这是因为原始数组索引在指针方面工作;例如,为了访问第二行,指向第一行的指针需要按行的大小递增。但是当行的大小是动态的时,数组不知道该大小,因此C++不知道如何进行指针增量。

如果你想要一个具有多个动态维度的数组,那么你需要构造数组分配,以便C++的默认数组索引逻辑可以处理它(例如这个重复问题的热门答案),或者你需要实现逻辑来自己找出适当的指针增量。

对于每行具有相同大小的数组,我建议不要使用多个分配,例如这些答案所建议的,或使用向量向量。使用向量向量可以解决手动分配的困难和危险性,但它仍然使用比必要更多的内存,并且不允许更快的内存访问模式。

另一种方法,扁平化多维数组,可以使代码像任何其他方法一样易于读写,不使用额外的内存,并且可以执行得更好。

扁平数组意味着您只使用与所需 2D 数组具有相同数量的元素的单个维度数组,并且您执行算术以在多维索引和相应的一维索引之间进行转换。使用new它看起来像:

int *arr = new int[row_count * column_count];

i 行,2d 数组中的第 j 列对应于 arr[column_count*i + j]arr[n]对应于第 n/column_count 行和第 n% column_count 列中的元素。例如,在包含 10 列的数组中,第 0 行第 0 列对应于 arr[0] ;第 0 行,第 1 列对应于arr[1];第 1 行 列 0 对应 arr[10] ;第 1 行,第 1 列对应于 arr[11]


您应该避免使用原始newdelete进行手动内存管理,例如在int *arr = new int[size];的情况下。相反,资源管理应该包含在 RAII 类中。用于管理动态分配的内存的 RAII 类的一个示例是 std::vector

std::vector<int> arr(row_count * column_count);
arr[column_count*i + j]

您可以将用于计算索引的逻辑进一步包装在另一个类中:

#include <vector>
class Array2d {
  std::vector<int> arr;
  int columns;
public:
  Array2d(int rows, int columns)
  : arr(rows * columns)
  , columns(columns)
  {}
  struct Array2dindex { int row; int column; };
  int &operator[] (Array2dindex i) {
    return arr[columns*i.row + i.column];
  }
};
#include <iostream>
int main() {
  int size;
  std::cin >> size;
  Array2d arr(size, size);
  for (int i = 0; i < size; ++i) {
    for (int j = 0; j < size; ++j) {
      arr[{i, j}] = 100;
    }
  }
  for (int i = 0; i < size; ++i) {
    for (int j = 0; j < size; ++j) {
      std::cout << arr[{i, j}] << ' ';
    }
    std::cout << 'n';
  }
}

如果你使用的是C++11,你也可以使用std::array。

const int iRows = 3, iCols = 3; // number of rows and columns
std::array<std::array<int, iCols>, iRows> matrix;
// fill with 1,2,3  4,5,6  7,8,9
for(int i=0;i<iRows;++i)
    for(int j=0;j<iCols;++j)
        matrix[i][j] = i * iCols + j + 1;

此类还允许使用函数进行边界检查

std::array::at

如果数组对象是常量限定的,则返回 const 引用,如果不是,则返回引用。请注意,

std::array

不是可变大小的数组类型,例如

std::vector
您可以使用

std::vector

std::vector<std::vector<int*>> a(size, std::vector<int*>(size));

这将创建一个动态分配的 2D int*数组,其宽度和高度等于 size

或者与new相同:

int*** a = new int**[size];
for (size_t i = 0; i < size; ++i)
    a[i] = new int*[size];
...
for (size_t i = 0; i < size; ++i)
    delete a[i];
delete a;

请注意,C++中没有new[][]接线员,您只需调用new[]两次即可。

但是,如果您想使用 newdelete 而不是 std::vector 来做到这一点,您应该使用智能指针而不是原始指针,例如:

std::unique_ptr<std::unique_ptr<int*>[]> a(new std::unique_ptr<int*>[size]);
for (size_t i = 0; i < size; ++i)
    a[i].reset(new int*[size]);
...
// No need to call `delete`, std::unique_ptr does it automatically.