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) 解决了问题。
我发现了一个我似乎无法解决的令人伤脑筋的问题。
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) 解决了问题。