我经常需要在编译时创建一个宽度和高度(让它们是n和m)未知的2D数组,通常我会写:
vector<int> arr(n * m);
我手动访问元素:
arr[j * m + i]
我最近被告知我可以写一下:
int arr[n][m] // n and m still only known at runtime.
所以这里有两个问题:
int (*)[n]
,但同样,n是动态的,在声明它的函数之外不知道(main
)。答案 0 :(得分:9)
您要问的功能(维度仅在运行时已知),是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
创建一个包装类,以便为您提供类似2-d的语法。
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';
答案 1 :(得分:2)
为什么没有std::vector
的{{1}}?
std::vector
访问项目然后变为:
std::vector<std::vector<int> > arr(n, std::vector<int>(m));
答案 2 :(得分:0)
std::vector
中的std::vector
(来自#include <vector>
)与二维数组的作用相同:
int n = 10, m = 10; //vector dimensions
std::vector<std::vector<int>> arr(n, std::vector<int>(m)); //Create 2D vector (vector will be stored as "std::vector<int> arr(n * m);
//you can get values from 2D vector the same way that you can for arrays
int a = 5, b = 5, value = 12345;
arr[a][b] = 12345;
std::cout << "The element at position (" << a << ", " << b << ") is " << arr[a][b] << "." << std::endl;
输出:
The element at position (5, 5) is 12345.