我该如何动态分配多维数组?
如果您已经知道嵌套维度的大小,您也可以使用 new 直接分配多维数组:
typedef int dimensions[3][4];
dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;
可以传递由运行时确定的值,而不是10
。由于它不是类型操作符new返回的一部分,因此被允许。如果你知道列数,但想保持行数可变,这将非常方便。typedef使代码更易读。
为了完整起见,以下是在你预先知道数组范围时以更好的方式在C++中执行它的方法。使用以下类的好处是,您不必担心在数据上调用delete[]。这意味着这个类将是异常安全的,并且所有关于RAII的其他优点也将得到体现。
template<typename T, int width, int height>
class MultiArray
{
private:
typedef T cols[height];
cols * data;
public:
T& operator() (int x, int y) { return data[x][y]; }
MultiArray() { data = new cols[width]; }
~MultiArray() { delete [] data; }
};
使用方法:
MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);
编辑:顺便说一下,如果你在运行时不知道数组边界,这里是你可以使用的设置:template<typename T>
class Array2D
{
private:
const int width;
T * data;
public:
T& operator() (int x, int y) { return data[y*width + x]; }
Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
~Array2D() { delete [] data; }
};
使用方法:
Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
#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;
}
std::vector<std::vector<int> >
应该被提及,因为它通常是最简单的方法。但是,请注意它是非矩形的。并不是每个std::vector<int>
都需要具有相同的长度。
boost::multi_array
是一个很棒的容器,而vector<vector<...>>
则适用于动态非常量长度数组...尽管这几乎从不需要...但当需要时,这就是正确的选择! - Elliott我很惊讶没有人提到boost::multi_array
。就在上周,我需要在程序中使用一个二维数组,并发现这比我之前自己编写的解决方案(其他评论中都提到了)更容易且编码速度更快。
int
块,而不是在我的for循环内创建新块,这样就不会在所有地方都引起页面错误。感谢eJames指出这段代码最初的问题。int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];
for ( int i = 0; i < height; ++i )
{
myArray[i] = data + (i*width);
}
// do some things here
delete[] data;
delete[] myArray;
您的循环不能正确地将指针值写入myArray
。我建议改为以下方式:
int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
myArray[i] = index;
index += height;
}
// ...
delete[] data;
delete[] myArray;
如果你正确地跨越了一定数量的元素,你可以将一维数组索引为二维、三维或 N 维数组。例如,如果我有 10 行和 10 列,我知道如果我在第 3 行,我至少要跨越 30 个元素才能到达它。
对于简单的二维数组,我更喜欢这种表示法,因为我不需要担心嵌套级别的指针。缺点是索引符号比较混乱。以下是一个具有 n 行和 m 列的二维数组的示例:
int *matrix = new int[n*m];
//set element (3,7) to 10
matrix[3*m+7] = 10;
//print the matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << matrix[i*m+j] << ' ';
}
cout << '\n';
}