假设我有以下简单结构:
struct Vector3
{
double x;
double y;
double z;
};
我创建了一个顶点列表:
std::vector<Vector3> verticesList;
除此之外,我还需要使用第三方库。该库具有以下签名的功能:
typedef double[3] Real3;
external void createMesh(const Real3* vertices, const size_t verticesCount);
将verticesList
转换为可以作为createMesh()
参数传递到vertices
的内容的最佳方式是什么?
目前我使用以下方法:
static const size_t MAX_VERTICES = 1024;
if (verticesList.size() > MAX_VERTICES)
throw std::exception("Number of vertices is too big");
Real3 rawVertices[MAX_VERTICES];
for (size_t vertexInd = 0; vertexInd < verticesList.size(); ++vertexInd)
{
const Vector3& vertex = verticesList[vertexInd];
rawVertices[vertexInd][0] = vertex.x;
rawVertices[vertexInd][1] = vertex.y;
rawVertices[vertexInd][2] = vertex.z;
}
createMesh(rawVertices, verticesList.size());
但肯定不是解决问题的最佳方式。
答案 0 :(得分:5)
这是一种正确的做法。还有其他一些方法......
类型Vector3
是与类型Real3
兼容的布局,其含义是您可以强制将指向一种类型的指针转换为另一种类型的指针:
createMesh( reinterpret_cast<Real3*>(&verticesList[0]), vertices.size() );
其他替代方案,正如Rook所提到的,删除循环正在使用memcpy
,因为类型是POD:
Real3 rawVertices[MAX_VERTICES];
std::memcpy( rawVertices, &verticesList[0],
vertices.size()*sizeof verticesList[0] );
这更简洁,可能更有效,但它仍然是复制整个容器。
我相信标准确实保证了这种行为(至少是C ++ 11),两种标准布局和标准兼容类型具有相同的内存布局(duh?)和§9.2p19状态:
指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然。
此保证在技术上意味着与我之前声称的略有不同:您可以reinterpret_cast<double*>(&verticesList[0])
指向verticesList[0].x
。但它也意味着通过重新解释演员从double*
到Real3
指针的转换也会没问题。