您询问的功能(尺寸仅在运行时才知道)是 C++ 的非标准扩展,但 C.99 的标准扩展(在 C.11 中成为可选功能)。该功能称为variable-length array (VLA),链接是GCC的文档。
如果您使用的是 GCC,那么您需要将数组的长度作为参数传递给函数。
void foo (int m, int arr[][m]) {
//...
}
然而,编译器或文档中似乎存在错误,因为上述函数原型语法仅在编译 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 创建一个包装器类,以便为您提供类似二维的语法。
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';