【问题标题】:std::vector<float> to std::vector<glm::vecX> without copyingstd::vector<float> 到 std::vector<glm::vecX> 不复制
【发布时间】:2016-01-04 00:02:44
【问题描述】:

我正在编写一个使用Tinyobjloader 加载.obj 文件的小型玩具游戏引擎。我使用glm::vecX 存储顶点数据和所有内容以使事情变得更容易。

当我想要一个std::vector&lt;glm::vecX&gt; 时,Tinyobjloader 给了我一个std::vector&lt;float&gt;。不抄袭怎么办?

需要明确的是,glm::vecX 是一个简单的结构,例如包含 float 成员 x, y, z

我在想,既然结构可以表现得有点像数组,那么std::move 会起作用,但没有运气。

谢谢!

编辑: 我知道我不清楚这一点,对不起。我想将std::vector&lt;float&gt; 移动到std::vector&lt;glm::vecX&gt; 或将其作为std::vector&lt;glm::vecX&gt;&amp; 传递。

使用std::memcpy 复制数据可以正常工作,但它会复制数据,我想避免这种情况。

【问题讨论】:

  • 你必须创建你自己的函数来实现它(它花费你 1)
  • glm::vecX的定义是什么?
  • xyz的成员有哪些类型?对应的float 值应该是什么?

标签: c++ vector struct glm-math


【解决方案1】:

有可能直接解释向量的内容作为结构的实例,而不必复制数据。如果你能保证表示是兼容的,那就是。 vector&lt;float&gt; 的内容在内存中以浮点值序列的形式排列在内存中,它们直接紧随其后(一个数组),没有额外的填充,而 vector&lt;glm::vecX&gt; 的内容以 vecX 序列的形式排列。因此,您需要确保满足以下条件:

  • glm::vecX 正好是 X 浮点数的大小,没有填充。根据结构的声明,这可能取决于平台。
  • vector&lt;float&gt; 的内容顺序正确,即 vec3 的 [x1,y1,z1,x2,y2,z2,...] 而不是 [x1,x2,..., xN,y1,y2...]。

在这种情况下,您可以安全地将浮点向量的数据指针重新解释为指向 vecX 数组的指针,如下例所示:

std::vector<float> myObjData = ...;
auto nVecs = myObjData.size() / 3; // You should check that there are no remainders!
glm::vec3* vecs = reinterpret_cast<glm::vec3*>(myObjData.data());
std::cout << vecs[0]; // Use vecs[0..nVecs-1]

但是,您不能安全地将 vector 本身重新解释为 glm::vecX 的矢量,甚至不能作为 const 矢量,因为存储在重新解释后向量可能不一致。这取决于vector&lt;T&gt;代码是直接存储元素的数量,还是分配的字节数(然后size()除以sizeof(T)):

// Don't do this, the result of .size() and .end() may be wrong!
const std::vector<glm::vec3>& bad = *reinterpret_cast<std::vector<glm::vec3>*>(&myObjData);
bad[bad.size()-1].z = 0; // Potential BOOM!

然而,大多数时候,您不需要传递实际的 vector,因为标准库中的大多数函数都接受 container range,这很容易给出第一个示例中的数组。因此,如果您想根据 z 位置对 vec3 数组进行排序,然后将其打印出来,您可以这样做:

// nVecs and vecs from the first example
std::sort(vecs, vecs+nVecs, // Sort by Z position
    [](const glm::vec3& a, const glm::vec3& b) { return a.z < b.z; });
std::copy(vecs, vecs+nVecs, std::ostream_iterator<glm::vec3>(std::cout, "\n"));

【讨论】:

  • 噢,太棒了!因为glm::vecX 应该是无填充的(这就是 glm 的重点)。现在,当然,正如你所说,这可能是平台相关的,所以我会在使用它之前检查它。 Check this outthis 了解更多信息。
【解决方案2】:

简而言之: - 据我所知 - 不复制是不可能的。

在我看来,std::memcpystd::vector 没有任何业务关系。

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2018-07-24
    • 2017-11-03
    • 2014-01-11
    • 2011-02-23
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    相关资源
    最近更新 更多