std::vector 的未指定行为与指向 object 的指针

Unspecified behaviour of std::vector with pointer to object

我发现了一个我似乎无法解决的令人伤脑筋的问题。

SceneSettings::SceneSettings()
{
    unsigned int w = (ConfigurationManager::GetInstance().GetWidth() >> 1) - 80;
    unsigned int h = (ConfigurationManager::GetInstance().GetHeight() >> 1) - 50;

    std::vector< std::string > menu_items;

    menu_items.push_back("Graphic Settings");
    menu_items.push_back("Sound Settings");
    menu_items.push_back("Game Settings");
    menu_items.push_back("Back");

    Label* aux = NULL;
    for ( unsigned int i = 0; i < menu_items.size(); i++ )
    {
        aux = new Label(menu_items[i], w, h);
        items.push_back(aux);
        aux = NULL;

        aux = new Label(menu_items[i], w, h);
        aux->SetColor(255, 0, 0);

        hover_section.push_back(aux);
        hover.push_back(false);

        aux = NULL;
        h += 25;
    }
}

SceneSettings::~SceneSettings()
{
    for (unsigned int i = 0; i < items.size(); i++)
    {
        delete items[i];
        delete hover_section[i];
    }

    items.clear();
    hover_section.clear();
}

void SceneSettings::Draw()
{
    for ( unsigned int i = 0; i < items.size(); i++ )
    {
        if (hover[i])
            hover_section[i]->Draw();
        else
            items[i]->Draw();
    }
}

void SceneSettings::HandleEvents(SDL_Event& event)
{
    switch(event.type)
    {
        case SDL_MOUSEMOTION :
        {
            int x = event.motion.x;
            int y = event.motion.y;

            for ( unsigned int i = 0; i < items.size(); i++ )
                hover[i] = items[i]->GetIsInLabel(x, y);
        } break;
    }
}

现在它所做的是,不显示第一个标签 "Graphic Settings"。 (不是看不见,就是明显看不见)

项定义为:

std::vector< Label* > items;
std::vector< Label* > hover_section;
std::vector< bool > hover;

出于某种原因,它不起作用,但是在另一个场景中 ("main_menu") 我有相同的标签向量(只有标题不同),它工作正常。

现在这个比看起来更有趣。因为它不仅不显示第一个项目,而且即使鼠标完全超出其范围,它也会显示第一个悬停项目。

如果我在 SceneSettings header 中将 std::vector 替换为直接 Label* menu_item_1,它会正确显示。这让我认为它与 std::vector

有关

我不太明白的另一件事是,如果我 运行 它处于调试模式并按步骤进行,它会正确显示,但是 watches 和调用堆栈都没有显示任何异常。

感谢任何帮助。

如果您在任何地方按值传递 SceneSettings 对象,无论是作为函数的参数还是返回此类对象,那么您 肯定 需要考虑在向量,或者必须实现复制构造函数和复制赋值运算符(如三规则所示)。

编译器创建的默认函数只会进行浅拷贝,即它会拷贝向量和指针,不会创建新的指针(深拷贝)。这会导致您有两个对象都包含指向向量中相同对象的指针,如果一个对象被破坏,如果将释放内存,使另一个对象带有杂散指针,这将导致未定义的行为。

原来问题出在Label class,其中我忽略了为GLSL 初始化纹理和缓冲区ID。在 Label 构造函数中向它们添加初始值 (0) 解决了问题。