int[n][m],其中n和m在运行时是已知的
int[n][m], where n and m are known at runtime
我经常需要在编译时创建一个宽度和高度未知的2D数组(让它们为n和m),通常我会写:
vector<int> arr(n * m);
我用手动访问元素
arr[j * m + i]
最近有人告诉我,我可以改为写:
int arr[n][m] // n and m still only known at runtime.
这里有两个问题:
- C++标准允许这种行为吗
- 我应该如何将这样的数组传递给函数?g++报告arr的类型为
int (*)[n]
,但同样,n是动态的,并且在声明它的函数(main
)之外是未知的
您询问的功能(只有在运行时才知道维度)是C++的非标准扩展,但却是C.99的标准扩展(在C.11中成为可选功能)。该功能被称为可变长度数组(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[]
以允许2维数组语法。
vector2d<int> v(n, m);
v[i][j] = 7;
std::cout << v[i][j] << 'n';
为什么不拥有std::vector
的std::vector
?
std::vector<std::vector<int> > arr(n, std::vector<int>(m));
访问一个项目然后变成:
std::cout << "(2,1) = " << arr[2][1] << std::endl;
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.
相关文章:
- CMake-按正确顺序将项目与C运行时对象文件链接
- 我在c++代码中生成了一个运行时#3异常
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 删除指向指针的指针是运行时错误吗
- 如何用参数值调用函数(仅在运行时已知)
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- c++中的指针和运行时错误
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 建议在运行时将带有类实例的列表从c++导入qml
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 读取文件时运行时的未知行为
- 构造一个可变参数模板化类,其中参数在运行时已知
- 是否可以使用C++对象组合,其中对象的选择是在运行时确定的
- 我可以得到std::array<double,dof>*arr,其中dof将已知运行时
- int[n][m],其中n和m在运行时是已知的
- 是否存在在连续内存中存储元素数组的STL容器,其中元素大小在运行时指定