C++ 向量推回VS安放推回

C++ 向量推回VS安放推回,c++,memory-management,stdvector,vulkan,C++,Memory Management,Stdvector,Vulkan,我有两种不同的方法向向量添加元素 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

我有两种不同的方法向向量添加元素

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\u顶点添加一个新元素

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\u顶点
向量中

下面是顶点的定义:

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);
        }
    };
}
memcpy(GUI_VertexAllocation->GetMappedData(), GUI_Vertices.data(), sizeof(Vertex) * GUI_Vertices.size());
我正在将内存从
GUI\u顶点
复制到一个预分配的缓冲区中,Vulkan将使用该缓冲区渲染顶点

现在我想弄清楚为什么第一种方法将
顶点
对象添加到
GUI_顶点
中总是有效,而第二种方法只是有时有效

这里是整个项目的链接

在重新编译项目之后,第二种方法偶尔会起作用,因此我在这里得到一些未定义的行为。我已经检查了
GUI\u顶点的有效性
,直到我们执行
memcpy
时,数据似乎是有效的,所以我不确定发生了什么

我想让第二种方法工作,这样我就可以有条件地将新顶点添加到缓冲区中

emplace\u back
将始终对其创建的对象执行值初始化,从而初始化所有数据成员。相比之下,
顶点NewVertex
将默认初始化对象,这会使其成员未初始化(因为GLM类型具有微不足道的默认构造函数)

因此,
pos.z
未初始化。你的代码不会自己初始化它。因此,您正在向GPU发送未初始化的垃圾

如果使用
顶点NewVertex{}创建对象,然后它将被初始化为值,就像
emplace\u back
那样

emplace\u back
将始终对其创建的对象执行值初始化,从而初始化所有数据成员。相比之下,
顶点NewVertex
将默认初始化对象,这会使其成员未初始化(因为GLM类型具有微不足道的默认构造函数)

因此,
pos.z
未初始化。你的代码不会自己初始化它。因此,您正在向GPU发送未初始化的垃圾


如果使用
顶点NewVertex{}创建对象,则将对其进行值初始化,就像
emplace\u back
一样。

当它不工作时会发生什么?@TanveerBadar它会在屏幕上画空白,就像在
memcpy
期间没有复制顶点数据一样。当它不工作时会发生什么?@TanveerBadar它会在屏幕上画空白,就像在
memcpy
期间没有复制顶点数据一样。
NewVertex.pos.x = ((float)x / 400) - 1.f;
NewVertex.pos.y = ((float)y / 300) - 1.f;
...
glm::vec3 pos;