std::vector<float> 到 std::vector<glm::vecX> 无需复制
std::vector<float> to std::vector<glm::vecX> without copying
我正在使用 Tinyobjloader for loading .obj files. I store the vertex data and everything using glm::vecX 编写一个小型玩具游戏引擎,以简化操作。
当我想要 std::vector<glm::vecX>
时,Tinyobjloader 给了我一个 std::vector<float>
。如果不复制我该怎么做?
明确地说,glm::vecX
是一个简单的结构,例如包含 float
成员 x, y, z
.
我在想,由于结构的行为有点像数组,所以 std::move 可以,但运气不好。
谢谢!
编辑:
我知道我对此不清楚,抱歉。我想将 std::vector<float>
移动到 std::vector<glm::vecX>
或将其作为 std::vector<glm::vecX>&
.
传递
使用 std::memcpy
复制数据工作正常,但它会复制数据,我想避免这种情况。
简而言之:据我所知,不复制是不可能的。
而且在我看来,std::memcpy
与 std::vector
没有任何关系。
可以直接将向量的内容解释为结构的实例,而不必复制数据。如果你能保证表示是兼容的,那就是。 vector<float>
的内容在内存中作为一系列浮点值排列(一个数组),没有额外填充,而 vector<glm::vecX>
的内容排列为一系列vecX。因此,您需要确保满足以下条件:
glm::vecX
正好是 X 浮点数的大小,没有填充。根据结构的声明,这可能是 platform-dependant.
vector<float>
的内容顺序正确,即 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]
但是,您不能安全地将 向量 本身重新解释为 glm::vecX 的向量,甚至不能将其解释为常量向量,因为向量中存储的元素数量在重新解释后可能不一致。这取决于 vector<T>
代码是直接存储元素的数量,还是分配的字节数(然后 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 范围,对于第一个示例中的数组,这很容易给出。所以,如果你想根据 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"));
我正在使用 Tinyobjloader for loading .obj files. I store the vertex data and everything using glm::vecX 编写一个小型玩具游戏引擎,以简化操作。
当我想要 std::vector<glm::vecX>
时,Tinyobjloader 给了我一个 std::vector<float>
。如果不复制我该怎么做?
明确地说,glm::vecX
是一个简单的结构,例如包含 float
成员 x, y, z
.
我在想,由于结构的行为有点像数组,所以 std::move 可以,但运气不好。
谢谢!
编辑:
我知道我对此不清楚,抱歉。我想将 std::vector<float>
移动到 std::vector<glm::vecX>
或将其作为 std::vector<glm::vecX>&
.
使用 std::memcpy
复制数据工作正常,但它会复制数据,我想避免这种情况。
简而言之:据我所知,不复制是不可能的。
而且在我看来,std::memcpy
与 std::vector
没有任何关系。
可以直接将向量的内容解释为结构的实例,而不必复制数据。如果你能保证表示是兼容的,那就是。 vector<float>
的内容在内存中作为一系列浮点值排列(一个数组),没有额外填充,而 vector<glm::vecX>
的内容排列为一系列vecX。因此,您需要确保满足以下条件:
glm::vecX
正好是 X 浮点数的大小,没有填充。根据结构的声明,这可能是 platform-dependant.vector<float>
的内容顺序正确,即 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]
但是,您不能安全地将 向量 本身重新解释为 glm::vecX 的向量,甚至不能将其解释为常量向量,因为向量中存储的元素数量在重新解释后可能不一致。这取决于 vector<T>
代码是直接存储元素的数量,还是分配的字节数(然后 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 范围,对于第一个示例中的数组,这很容易给出。所以,如果你想根据 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"));