【问题标题】:How to convert a stl vector of 3-element structs into 2D C-style array如何将 3 元素结构的 stl 向量转换为 2D C 样式数组
【发布时间】:2012-06-13 12:52:12
【问题描述】:

假设我有以下简单的结构:

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 转换为可以作为vertices 参数传递给createMesh() 的最佳方法是什么?

目前我使用以下方法:

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());

但这肯定不是解决问题的最佳方法。

【问题讨论】:

  • 这种方法具有可读性强的优点。您可能会发现 Vector3 数组在内存中的排列方式与浮点数组完全相同;重新解释演员表或 memcpy 可能会以更简短的方式解决您的问题。但是,我懒得自己检查。
  • 我想你可以为Vector3-&gt;Real3 实现一个转换运算符并传递&amp;verticesList[0]
  • @chris:来自Vector3的转换->Real3不会从Vector3*转换->Real3*
  • @DavidRodríguez-dribeas,哎呀,对。我在考虑reinterpet_cast,但转换似乎更合适(如果可行的话)。

标签: c++ arrays stl


【解决方案1】:

这是一个正确的做法。还有一些其他的方法...

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),两种标准布局和标准兼容类型具有相同的内存布局(呃?),并且 §9.2p19 规定:

一个指向标准布局结构对象的指针,使用 reinterpret_cast 进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。

这个保证在技术上意味着与我之前声称的稍有不同:您可以将reinterpret_cast&lt;double*&gt;(&amp;verticesList[0]) 指向verticesList[0].x。但这也意味着通过 reinterpret cast 从double*Real3 指针的转换也可以。

【讨论】:

  • reinterpret_cast 在 void* 和整数类型或整数类型指针上的其他东西是 UB,除非您将其转换回其原始类型。
  • 当然,reinterpret_cast 是最快、最短的方法,但它显然容易出错。例如,如果我决定将 Vector3 中的 double 更改为 float,则几乎不可能找到错误的转换。
  • @JoelFalcou:以上来自 C++11 标准的引用似乎不同意您的观点,并明确指出 reinterpret_cast 从标准布局类型到第一个成员并返回是明确定义的。此外,5.2.10p7 规定:当类型为“指向 T1 的指针”的纯右值 v 转换为类型“指向 cv T2”的纯右值时,结果为 static_cast(static_cast( v)) 如果 T1 和 T2 都是标准布局类型,这似乎再次提供了明确定义的语义。
  • @DmitrySapelnikov:同意,这是该语言中第二危险的演员表(仅次于 c 风格演员表,只是因为它实际上可以是 reinterpret_cast 在引擎盖下,允许丢弃 const- ness 并且在浏览代码时不会像 beware 那样大声喊叫)。与reinterpret_cast打交道时需要格外小心。
  • 我的立场是正确的,这可能是对这种做法的标准升级。考虑我也更新了。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 2021-10-22
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多