Vector Push_Back VS Emplace_Back
Vector Push_Back VS Emplace_Back
我有两种不同的方法将元素添加到向量中。
GUI_Vertices.emplace_back();
GUI_Vertices.back().pos.x = ((float)x / 400) - 1.f;
GUI_Vertices.back().pos.y = ((float)y / 300) - 1.f;
GUI_Vertices.back().texCoord.x = u;
GUI_Vertices.back().texCoord.y = v;
GUI_Vertices.back().color.r = m_Color.r / 128;
GUI_Vertices.back().color.g = m_Color.g / 128;
GUI_Vertices.back().color.b = m_Color.b / 128;
GUI_Vertices.back().color.a = m_Color.a / 128;
上面的代码有效,但是我被迫向GUI_Vertices
向量添加一个新元素。
Vertex NewVertex;
NewVertex.pos.x = ((float)x / 400) - 1.f;
NewVertex.pos.y = ((float)y / 300) - 1.f;
NewVertex.texCoord.x = u;
NewVertex.texCoord.y = v;
NewVertex.color.r = m_Color.r / 128;
NewVertex.color.g = m_Color.g / 128;
NewVertex.color.b = m_Color.b / 128;
NewVertex.color.a = m_Color.a / 128;
GUI_Vertices.emplace_back(NewVertex);
上面的代码有时有效,如果需要,我可以有条件地将NewVertex
添加到GUI_Vertices
向量中。
以下是Vertex
的定义:
struct Vertex {
glm::vec3 pos;
glm::vec4 color;
glm::vec2 texCoord;
static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions = {};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex& other) const {
return pos == other.pos && color == other.color && texCoord == other.texCoord;
}
};
namespace std {
template<> struct hash<Vertex> {
size_t operator()(Vertex const& vertex) const {
return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec4>()(vertex.color) << 1)) >> 1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1);
}
};
}
稍后在程序执行中,将所有Vertex
元素添加到GUI_Vertex
向量后,我对GUI_Vertex
执行以下操作:
memcpy(GUI_VertexAllocation->GetMappedData(), GUI_Vertices.data(), sizeof(Vertex) * GUI_Vertices.size());
我正在将内存从GUI_Vertices
复制到一个预分配的缓冲区中,Vulkan 将使用该缓冲区来渲染我们的顶点。
现在我试图弄清楚为什么将Vertex
对象添加到GUI_Vertices
中的第一种方法总是有效,而第二种方法有时才有效。
这是整个项目 https://github.com/kklouzal/WorldEngine/blob/GUI_Indirect_Draw/Vulkan/VulkanGWEN.hpp 的链接
重新编译项目后,第二种方法偶尔会起作用,所以我在这里得到了一些未定义的行为。我已经检查了GUI_Vertices
的有效性,直到我们进行memcpy
并且数据似乎是有效的,所以我不确定发生了什么。
我想让第二种方法工作,以便我可以有条件地将新顶点添加到缓冲区中。
NewVertex.pos.x = ((float)x / 400) - 1.f; NewVertex.pos.y = ((float)y / 300) - 1.f; ... glm::vec3 pos;
emplace_back
将始终对其创建的对象执行值初始化,从而初始化所有数据成员。相比之下,Vertex NewVertex;
将默认初始化对象,从而使其成员未初始化(因为 GLM 类型具有简单的默认构造函数(。
所以pos.z
是未初始化的。而且您的代码不会自己初始化它。因此,您正在将未初始化的垃圾发送到 GPU。
如果使用Vertex NewVertex{};
创建对象,则它将像emplace_back
一样进行值初始化。
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 推导 std::vector::back() 的返回类型
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- vector.push_back(vector.back()+1) 是未定义的行为吗?
- 不为 emplace() 定义构造函数的解决方法
- 如何提取由 unordered_map::emplace 重新调整的货币对的值?
- 如何最好地将 emplace 与 std::map 一起使用
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- std::vector::emplace() 真的在面对抛出移动构造函数/赋值运算符时提供了强大的异常保证吗?
- std::map::emplace无法解决,但插入右值有效 - 为什么?
- vector.back()和vector.end()有什么区别
- 为什么 std::map emplace 需要在 gcc 上有一个复制构造函数
- 为什么unordered_map的 emplace piecewise_construct参数需要默认构造函数?
- std::元组到元组的映射和使用 emplace
- 列表大小为 1,但 front() 和 back() 不相等
- 如何使用 emplace 添加到C++中的地图
- C++ map emplace