我有一个名为SolidObject的类,它包含指向第一个数组元素的各种指针:
// Member declaration and definition pulled together from .cpp and .h
class SolidObject {
//I will only use one variable as demonstration, the others behave the same
protected:
float* vertices;
public:
SolidObject(float[] vertices) {
this->vertices = vertices;
}
}
对于实验,我曾经将硬编码数组传递给构造函数,例如
float vertices[] {
-5,0,-5,
5,0,-5,
-5,10,-5,
-5,0,5,
5,10,-5,
5,0,5,
-5,10,5,
5,10,5
};
SolidObject cube (vertices);
现在我正在将斯坦福PLY文件中的值解析为std::vector
,然后将其传递给构造函数:
std::vector<float> vertices;
for (...) {
vertices.push_back(....);
}
SolidObject cube (&vertices[0]);
使用此方法,cube->vertices
中指向的值在运行时期间没有任何原因发生变化。这是watch coinObject->vertices[0]
的GDB观察点输出:
这是WP第一次被触发。这是预期的,因为vertices
是使用默认(void)构造函数时的NULL指针。 coinObject首先被定义,然后被初始化,所以这种行为是预期的。
Hardware watchpoint 1: coinObject->vertices[0]
Old value = <unreadable>
New value = 0.100000001
0x0000000000409c69 in gameloop (screen=0x689cc0, font=0x84a020)
at ../gameloop.cpp:386
386 coinObject = SolidObject::fromFile("/home/sebastian/coin.ply");
(gdb) c
Continuing.
现在出现了我无法向自己解释的内容:
Hardware watchpoint 1: coinObject->vertices[0]
Old value = 0.100000001
New value = 0
0x0000003852c8d4b1 in memset () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) c
Continuing.
Hardware watchpoint 1: coinObject->vertices[0]
Old value = 0
New value = 1.40129846e-45
0x00007ffff63df548 in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
(gdb) c
Continuing.
这次在这两次更改后它停止了,有时候coinObject->vertices[0]
会有数千次更改。有时程序甚至在第一次或第二次更改后崩溃,因为使用这些数组的OpenGL无法找到224中的百万个顶点。(我使用glDrawElements
的索引数组,但这对我的问题不重要...)
任何人都可以解释为什么会发生这种情况以及如何解决它?
答案 0 :(得分:1)
如果您在对象中使用vector
,则代码会更安全:
class SolidObject
{
std::vector<float> vertices;
public:
SolidObject(const std::vector<float>& original_vertices)
: vertics(original_vertices)
{
}
};
如果您传递给vector
版本的SolidObject
曾经调整大小,那么指向浮点数的指针将不再有效并指向垃圾。
另外,为什么使用float
代替double
来降低精确度?
如果您希望SolidObject
使用相同的向量,您可以使用引用作为数据成员:
class SolidObject
{
std::vector<float>& vertices;
public:
SolidObject(std::vector<float>& v)
: vertices(v)
{
// Look, no "this" pointer. :-)
}
};