vector<vector<int>>(或 vector<vector<int> >,对于较旧的编译器)可以很好地工作,但它不一定是最有效的方法1。另一个可以很好地工作的是单个向量的包装器,它跟踪所表示的矩阵的“形状”,并提供一个函数或重载运算符来访问数据:
template <class T>
class matrix {
int columns_;
std::vector<T> data;
public:
matrix(int columns, int rows) : columns_(columns), data(columns*rows) {}
T &operator()(int column, int row) { return data[row*columns_+column]; }
};
请注意,C++ 标准只允许operator[] 采用单个操作数,因此您不能将它用于这项工作,至少不能直接使用。在上面的示例中,我(显然)使用了operator(),所以下标看起来更像 Fortran 或 BASIC,而不是您在 C++ 中所习惯的。如果你真的打算使用[] 表示法,无论如何你都可以这样做,尽管它有点棘手(你在矩阵类中重载它以返回代理,然后让代理类也重载operator[] 以返回(a参考)正确的元素——它在内部有点难看,但无论如何工作得很好)。
这是一个如何使用operator[] 的多个重载来实现版本的示例。我在大多数编译器包含std::vector 之前写了这个(很长一段时间),所以它静态分配一个数组而不是使用一个向量。它也适用于 3D 案例(因此涉及到两个级别的代理),但幸运的是,基本的想法还是通过了:
template<class T, int size>
class matrix3 {
T data[size][size][size];
friend class proxy;
friend class proxy2;
class proxy {
matrix3 &m_;
int index1_, index2_;
public:
proxy(matrix3 &m, int i1, int i2)
: m_(m), index1_(i1), index2_(i2)
{}
T &operator[](int index3) {
return m_.data[index1_][index2_][index3];
}
};
class proxy2 {
matrix3 &m_;
int index_;
public:
proxy2(matrix3 &m, int d) : m_(m), index_(d) { }
proxy operator[](int index2) {
return proxy(m_, index_, index2);
}
};
public:
proxy2 operator[](int index) {
return proxy2(*this, index);
}
};
使用它,您可以使用正常的 C++ 语法来寻址矩阵,例如:
matrix3<double, size> m;
for (int x=0; x<size; x++)
for (int y = 0; y<size; y++)
for (int z = 0; z<size; z++)
m[x][y][z] = x*100 + y * 10 + z;
-
std::vector 通常实现为指向一些动态分配的数据的指针,因此像vector<vector<vector<int>>> 这样的东西将取消引用两级指针以获取每条数据。这意味着更多的内存引用,这在大多数现代处理器上往往相当慢。由于每个向量都包含单独分配的数据,因此通常也会导致缓存局部性不佳。它也可能会浪费一些空间,因为每个向量都存储其分配的大小和正在使用的大小。