我在c ++中查看Modern OpenGL的示例,其中结构用于保存有关顶点坐标和3坐标颜色矢量的数据
struct VertexData{
float x, y;
float r, g, b;
}
std::vector<VertexData> myData = {
{.x = 0, .y = 0, .r = 0, .g = 0, .b = 0},
{.x = 0, .y = 0, .r = 0, .g = 0, .b = 0}
}
float *ptr = (float*) &myData[0];
要访问向量的第二个元素的x值,我可以访问用于将顶点缓冲区传递给OpenGL的技术ptr[5]
。我的问题是:我可以在更复杂的课程中使用同样的技术吗?举一个具体的例子,如果我有一个Vertex
类:
class Vertex {
public:
float x, y, z;
Vertex();
// Other constructors here...
Vertex operator+(const Vertex &other);
// Overload of other operators like -,*,=, etc...
}
std::vector<Vertex> myData(100);
float *ptr = (float*) &myData[0];
使用ptr
变量访问此向量中的所有元素仍然是安全的(并且一个好主意......)我知道在静态变量,不同类型,继承等存在的情况下这可能很棘手,但在这种情况下,只有普通变量和函数作为成员,使用指针是可靠进场?
答案 0 :(得分:-1)
根据C ++标准,此技术具有未定义的行为。编译器可以在成员之间添加填充。所以,根据标准的原则,这是一个坏主意。
然而。
我知道的所有编译器(我在过去15年中使用过8种不同的C ++编译器),在这种情况下不添加填充。他们为什么?所以,如果你敢于进入未定义行为的土地,你可以使用这种技术。即使在复杂的情况下。继承,虚函数等我所知道的所有编译器都是逻辑的,并且在你的情况下将float成员彼此相邻放在内存中,并且它们的优化器在这种情况下不会失败。注意:该标准允许编译器在访问说明符之间重新排序成员,因此如果您想要安全(您已经离开),请将所有成员放在相同的访问说明符下(仍然,我还没有看到编译器) ,实际上是在访问说明符之间重新排序成员。)。
因此。 可靠吗?根据标准:否。根据目前的做法:根据我的经验,是的。我还没有看到编译器,这样的代码失败了。我鼓励任何知道这种编译器的人不要保持沉默,并将其添加为答案。
注意:这是当前状态。它可能会打破任何时间。如果你知道自己在做什么,我只会建议使用这种技术,并且你知道可能的后果。不要忘记在你的代码中评论这个事实。