你所询问的特性(在运行时才知道维度)是C++的一个非标准扩展,但是在C.99中是标准扩展(在C.11中成为可选特性)。该特性被称为
变长数组(VLA),链接是GCC的文档。
如果你使用的是GCC,则需要将数组长度作为参数传递给函数。
void foo (int m, int arr[][m]) {
}
然而,无论是编译器还是文档中似乎存在一个 bug,因为上述函数原型语法只适用于编译 C 代码,而不适用于 C++(截至 gcc 版本 4.8.2)。我找到的唯一解决方法是使用 void * 参数,并在函数体中进行强制转换:
int foo_workaround (int m, void *x)
{
int (*arr)[m] = static_cast<int (*)[m]>(x);
}
如果您不想依赖编译器扩展,还有其他的解决方案。如果您不介意为每一行单独分配内存,您可以使用向量的向量,例如:
std::vector<std::vector<int> > arr(n, std::vector<int>(m))
然而,如果你想要像你自己的示例中展示的那样一个单一分配块,那么最好创建一个包装器类来围绕vector
给你类似2D的语法。
template <typename T>
class vector2d {
int n_;
int m_;
std::vector<T> vec_;
template <typename I>
class vector2d_ref {
typedef std::iterator_traits<I> TRAITS;
typedef typename TRAITS::value_type R_TYPE;
template <typename> friend class vector2d;
I p_;
vector2d_ref (I p) : p_(p) {}
public:
R_TYPE & operator [] (int j) { return *(p_+j); }
};
typedef std::vector<T> VEC;
typedef vector2d_ref<typename VEC::iterator> REF;
typedef vector2d_ref<typename VEC::const_iterator> CREF;
template <typename I>
vector2d_ref<I> ref (I p, int i) { return p + (i * m_); }
public:
vector2d (int n, int m) : n_(n), m_(m), vec_(n*m) {}
REF operator [] (int i) { return ref(vec_.begin(), i); }
CREF operator [] (int i) const { return ref(vec_.begin(), i); }
};
包装器的
operator[]
返回一个中间对象,该对象还重载了
operator[]
,以在使用包装器时允许二维数组语法。
vector2d<int> v(n, m);
v[i][j] = 7;
std::cout << v[i][j] << '\n';
vector<vector<int>>
。 - matsjoyce