这是关于良好实践的问题
考虑典型的情况,例如在 3D 引擎、物理引擎、有限元方法或经典分子动力学求解器中:您有各种类型的对象(例如顶点、边、面、有界实体体积),它们相互交联(例如顶点知道哪条边连接到它,反之亦然)。对于此类引擎的性能和使用便利性,对于能够快速浏览此类连接的网络至关重要。
问题是:通过数组中的索引或指针指向链接对象更好吗?...尤其是在性能方面
typedef index_t uint16_t;
class Vertex{
Vec3 pos;
#ifdef BY_POINTER
Edge* edges[nMaxEdgesPerVertex];
Face* faces[nMaxFacesPerVertex];
#else
index_t edges[nMaxEdgesPerVertex];
index_t faces[nMaxFacesPerVertex];
#endif
}
class Edge{
Vec3 direction;
double length;
#ifdef BY_POINTER
Vertex* verts[2];
Faces* faces[nMaxFacesPerEdge];
#else
index_t verts[2];
index_t faces[nMaxFacesPerEdge];
#endif
}
class Face{
Vec3 normal;
double isoVal; // Plane equation: normal.dot(test_point)==isoVal
#ifdef BY_POINTER
Vertex* verts[nMaxVertsPerFace];
Edge* edges[nMaxEdgesPerFace];
#else
index_t verts[nMaxVertsPerFace];
index_t edges[nMaxEdgesPerFace];
#endif
}
#ifndef BY_POINTER
// we can use other datastructure here, such as std:vector or even some HashMap
int nVerts,nEdges,nFaces;
Vertex verts[nMaxVerts];
Edge edges[nMaxEdges];
Vertex faces[nMaxFaces];
#endif
指数优势:
uint8_t
当我们使用或uint16_t
用于索引而不是 32 位或 64 位指针时,使用索引可以更节省内存- 索引可以携带一些以某些位编码的附加信息(例如关于边缘的方向);
- 数组中对象的排序可以携带一些关于结构的信息(例如,立方体的顶点可以排序为
{0b000,0b001,0b010,0b011,0b100,0b101,0b110,0b111}
)。此信息在指针中不可见
指针的优点:
- 我们不需要关心数组(或其他数据结构)来存储对象。对象可以简单地在堆上动态分配
new Vertex()
。 - 可能更快(?),因为它不需要添加数组的基地址(?)。但这在内存延迟方面可能可以忽略不计(?)