如何让VC++以2D数组的形式访问指针
How to get VC++ to access a pointer as a 2D array
我正在做一些图形编程,我有一个二维数组(在程序执行过程中大小不同),我使用openGL存储
所以当我访问它时,我得到的只是一个void
指针。
为了使逻辑更简单,我希望编译器假装它是2D数组,并将其用作2D数组(因为arr[i][j]
比ptr[i * y + j]
更简洁,更不容易出错)。
我发现这种巧妙的选角方法在GCC(在大学的linux机器上)中运行良好:
Vertex (&vertices)[tess][tess] = *reinterpret_cast<Vertex (*)[tess][tess]>(
glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)
);
它基本上将openGL给我的内存指针块强制转换为tess X tess
2D数组,并创建该类型的引用来指向它。
这允许我访问类似vertices[i][j]
的内存Vertex
只是包含float
s的typedef
ed struct
然而,在家里的Windows机器上,VS'12有一个嘶嘶作响的拟合,抱怨它要求tess
所写的整数为constant
(特别是error C2057: expected constant expression
)
我不知道为什么。
现在,我知道VS不支持VLA,但我不是在这里创建数组,我是在创建一个引用,直到运行时我才知道它的大小
所以它不应该在意函数调用之间的大小是否发生变化,对吧?为什么不允许这样做?
为了不被吓倒,我尝试使用std::array
std::array<std::array<Vertex, tess>, tess>& vertices;
除了明显的references must be initialized
之外,这个测试对我没有帮助,因为它仍然抱怨expression must have a constant value
(特别是error C2975: '_Size' : invalid template argument for 'std::array', expected compile-time constant expression
)
我不知道该在这里尝试什么,我为reinterpret_cast
及其简单的制作方式感到骄傲,并确信我使用的方法没有违反标准
我不想从指针创建std::vector
,然后在完成后将数据从该动态数组复制回指针位置;当内存块已经放在那里的时候,这似乎太低效了
没有办法在一个预先存在的内存块周围创建一个向量,是吗。。不,听起来很傻。
我想看看这是否可以在不放弃的情况下完成,并将其用作Vertex*
;想法
有人能告诉我为什么它在VS中不起作用吗
我能做些什么让它正常工作吗(VS的扩展/更新)
VS'13是否增加了对此的支持?
我还得到了无法解释的错误C2087: 'vertices' : missing subscript
以及这些似乎表明VS迫切希望tess
保持恒定的其他错误:error C2466: cannot allocate an array of constant size 0
error C2540: non-constant expression as array bound
error C2440: 'initializing' : cannot convert from 'Vertex [1][1]' to 'Vertex (&)[][1]'
这很有趣;我实现了一个类来处理我想要的东西
它并不像我想要的那样类型安全,但我通过它学到了很多
就像我在发现jQuery之前为javascript实现"应该是指定的一部分"的语法糖式功能一样。
基本上,而不是能够做到这一点。
int (&array)[x][y] = *reinterpret_cast<int (*)[x][y]>(pointer);
你必须做这个
MDAI<int, 2> array = MDAI<int, 2>(pointer, x, y);
但除此之外,它的工作完美无瑕!:D
我最初只写了一个专门的TwoDArray类,但发现我实际上也有一些3D阵列
因此,我没有实现3D版本(当你深入研究时,它返回了TwoDArray),而是做了一些更通用的东西,可以帮助你处理任意维度的数组。
#include <Windows.h>
#include <iostream>
/*MultiDimensional Array Interpretation
has the compiler use a flat pointer reference as if it were a faceted array
C++11/GCC VLA-supporting equivalent:
int (&array)[x][y] = *reinterpret_cast<int (*)[x][y]>(pointer);
using MDAI, <C++11 and MSVS compatible:
MDAI<int, 2> array = MDAI<int, 2>(pointer, x, y);
*/
template<class Type, unsigned int dimension>
class MDAI {
private:
Type* array;
//+1 to guard against zero-length-array
unsigned int bounds[dimension + 1];
public:
//unfortunately I can't use `unsigned int &(dimensions)[dimension]` to make it safe
//because of how operator[]() tries to construct its return value
/*constructor*/
MDAI(Type* array, unsigned int* bounds)
: array(array)
{
std::copy(bounds, bounds + dimension, this->bounds);
}
/*programmer usable constructor for typing of the dimensions, instead of having to declare an array*/
MDAI(Type* array, ...)
: array(array)
{
va_list arguments;
va_start(arguments, array);
for (int index = 0; index < dimension; ++index)
bounds[index] = va_arg(arguments, unsigned int);
va_end(arguments);
}
/*drills down one level into the multi dimensional array*/
MDAI<Type, dimension - 1> operator[](unsigned index) {
if (dimension < 1) {
std::cerr << "MDAI is not an array.n";
throw 1;
}
if (index < 0 || index >= bounds[0]) {
std::cerr << "Index out of bounds.n";
throw 1;
}
//figure out how many addresses to jump
for (unsigned int index2 = 1; index2 < dimension; ++index2)
index *= bounds[index2];
return MDAI<Type, dimension - 1>(array + index, bounds + 1);
}
/*'dereferences' the array to get a reference to the stored value*/
Type& operator*() {
if (dimension > 0) {
std::cerr << "MDAI is an array.n";
throw 1;
}
return *array;
}
/*allows the compiler to automagically 'convert' the MDAI into whatever the user thinks it is*/
operator Type&() {
return **this;
}
/*makes assignment work automagically too!*/
MDAI<Type, dimension>& MDAI<Type, dimension>::operator=(Type value) {
**this = value;
return *this;
}
};
测试边界的三维阵列2-4-3:
void main(unsigned int argC, char** argV) {
using namespace std;
int array[2][4][3] = {
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{10, 11, 12}
},
{
{13, 14, 15},
{16, 17, 18},
{19, 20, 21},
{22, 23, 24}
}
};
//cast array to pointer, then interpret
MDAI<int, 3> mdai((int*)array, 2, 4, 3);
//testing correct memory access
cout << 15 << ' ' << mdai[1][0][2] << endl;
//testing modifcations using mdai are in array
mdai[0][2][1] = -1;
cout << array[0][2][1] << ' ' << mdai[0][2][1] << endl;
//testing modifications in array show up in mdai
array[1][3][2] = -23;
cout << -23 << ' ' << mdai[1][3][2] << endl;
//testing automatic type casting
cout << -15.0 << ' ' << mdai[0][0][1] * -7.5 << endl;
}
它就像我把它作为数组引用时一样无缝。
为了编译时的安全性,我想将operator*()
重新声明为Type& MDAI<Type, 0>::operator*()
所以你只能在<X、 0>
但我想不通
类似地,使operator[]()
仅出现在大于0的维度
哦,运行时检查必须足够好
- C++ - 循环访问指针数组会导致错误
- 如何访问指针结构的成员变量?
- 从子线程访问指针
- 如何在C++中使用类对象访问指针数据成员
- 如何使用二维语法访问指针
- 我可以保证以负偏移访问指针吗?
- 是否访问指针元组和互斥锁线程安全
- 如何从嵌套类中访问指针
- C++ 如何访问指针的结构变量
- 从地图擦除后访问指针
- 会员在共享_ptr上访问指针
- 删除后访问指针
- 为什么在递增后使用 [] 运算符访问指针数组会返回错误地址的当前内存位置
- 如何在python脚本中使用Pybind11修改/访问C++指针
- 无法从另一个函数访问指针数组
- 无法访问指针C 的值
- 访问指针类成员 (C++)
- 访问指针数组中的子类方法
- 访问指针到结构中的向量
- 访问指针类型的静态属性