gpt4 book ai didi

c++ - vector Push_Back VS Emplace_Back

转载 作者:行者123 更新时间:2023-12-01 15:05:23 27 4
gpt4 key购买 nike

我有两种不同的方法可以将元素添加到 vector 中。

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 vector 添加一个新元素。
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 vector 中。

这是 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 vector 后,我对 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一样对它进行值初始化。

关于c++ - vector Push_Back VS Emplace_Back,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59009614/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com