C++使用二维数组的两种方法

今天看到Stackoverflow上有一个如何在C++中申请动态数组的问题,其中讲了两种不同的方法申请动态数组,谨以此记。

方法一:直接申请动态数组

C++11申请行方向定长数组

假如行的长度是编译期常数,则在C++11中可以直接使用:

1
auto arr2d = new int [nrows][CONSTANT];
申请动态数组。

数组的数组

假如不是如此,则可以使用数组的数组的方式申请动态数组:

1
2
3
int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
a[i] = new int[colCount];

GNU拓展:变长数组

GCC(G++)允许以以下方式申请动态数组:

1
double (* in)[n][n] = new (double[m][n][n]);

方法二:用一维数组模拟二维数组

直接申请存在的问题

直接申请的二维数组实际上是数组的数组,不同行之间的内存并不一定相邻导致cache miss,且申请时存在额外开销(时间上和空间上)。所以使用一维数组进行模拟二维数组是较为高效的。

简单模拟方法(使用at寻找索引)

这是Stackoverflow上评论区给出的一个版本。

1
2
3
4
5
6
7
8
9
10
class Matrix {
int* array;
int m_width;
public:
Matrix( int w, int h ) : m_width( w ), array( new int[ w * h ] ) {}
~Matrix() { delete[] array; }
int at( int x, int y ) const { return array[ index( x, y ) ]; }
protected:
int index( int x, int y ) const { return x + m_width * y; }
};

难一些的模拟方法(重载运算符)

这是Stackoverflow上评论区给出的一个版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Grid {
size_t _rows;
size_t _columns;
std::unique_ptr<int[]> data;

public:
Grid(size_t rows, size_t columns)
: _rows{rows},
_columns{columns},
data{std::make_unique<int[]>(rows * columns)} {}

size_t rows() const { return _rows; }

size_t columns() const { return _columns; }

int *operator[](size_t row) { return row * _columns + data.get(); }

int &operator()(size_t row, size_t column) {
return data[row * _columns + column];
}
}