改变一个指针后乘法对象改变
Multiply object is changed after changing one pointer
我只是在做一个 Uni 任务,虽然它很简单。但是我卡住了。
任务很简单,就是用SDL2做一个输入映射系统。我创建了一个 Button 结构,其中包含按钮的名称、矩形和分配的键。
vector<Button>buttons = {
Button("up", SDL_Rect{ 100,100,100,20 },"Up"),
Button("down", SDL_Rect{ 100,200,100,20 },"Down"),
Button("left", SDL_Rect{ 100,300,100,20 },"Left"),
Button("right", SDL_Rect{ 100,400,100,20 },"Right"),
Button("reset", SDL_Rect{ 400,400,100,20 },"R")
};
然后当单击鼠标并且鼠标位置在其中一个按钮内时,它会将 clickedButton 指针分配给该按钮。
if (evt.type == SDL_MOUSEBUTTONDOWN)
{
int x, y;
SDL_GetMouseState(&x, &y);
for (auto &b : buttons)
{
if (x > b.btn_rect.x && x<(b.btn_rect.x + b.btn_rect.w) && y > b.btn_rect.y && y < (b.btn_rect.y + b.btn_rect.h))
{
cout << "Button " << b.btn_name << " clicked" << endl;
btClicked = &b;
break;
}
}
}
现在奇怪的事情发生了。当 btClicked 不为 null 时,我会为这个按钮分配一个键名。但是每次我将另一个按钮分配给 btClicked 之前分配给 btClicked 的按钮也会更改它的键名。
if (evt.type == SDL_KEYDOWN)
{
if(btClicked!=NULL)
{
btClicked->assigned_key = SDL_GetKeyName(evt.key.keysym.sym);//breakpoint here
btClicked = NULL;
}
下面可以看到断点调试。所有先前分配给 btClicked 的按钮都已更改。但是 btClicked 只是指向其中一个按钮。
The breakpoint Debug
有人知道这里发生了什么吗?请帮忙。
SDL_GetKeyName
的return值指向的字符串只保证在下一次调用SDL_GetKeyName
之前有效。在这种情况下,看起来它有一个静态缓冲区,每次调用都会重复使用该缓冲区,因此您的所有 Button
最终都指向同一个字符串。这意味着如果您需要它保持有效更长时间,您需要复制该字符串。
实现此目的的最简单方法是让您的 Button::assigned_key
成员成为 std::string
而不是原始 const char*
.
无论如何,这几乎总是一个好主意,因为在对象中保留 const char*
成员会混淆所有权语义,并使应用程序更容易出现此类错误和内存泄漏。
我只是在做一个 Uni 任务,虽然它很简单。但是我卡住了。 任务很简单,就是用SDL2做一个输入映射系统。我创建了一个 Button 结构,其中包含按钮的名称、矩形和分配的键。
vector<Button>buttons = {
Button("up", SDL_Rect{ 100,100,100,20 },"Up"),
Button("down", SDL_Rect{ 100,200,100,20 },"Down"),
Button("left", SDL_Rect{ 100,300,100,20 },"Left"),
Button("right", SDL_Rect{ 100,400,100,20 },"Right"),
Button("reset", SDL_Rect{ 400,400,100,20 },"R")
};
然后当单击鼠标并且鼠标位置在其中一个按钮内时,它会将 clickedButton 指针分配给该按钮。
if (evt.type == SDL_MOUSEBUTTONDOWN)
{
int x, y;
SDL_GetMouseState(&x, &y);
for (auto &b : buttons)
{
if (x > b.btn_rect.x && x<(b.btn_rect.x + b.btn_rect.w) && y > b.btn_rect.y && y < (b.btn_rect.y + b.btn_rect.h))
{
cout << "Button " << b.btn_name << " clicked" << endl;
btClicked = &b;
break;
}
}
}
现在奇怪的事情发生了。当 btClicked 不为 null 时,我会为这个按钮分配一个键名。但是每次我将另一个按钮分配给 btClicked 之前分配给 btClicked 的按钮也会更改它的键名。
if (evt.type == SDL_KEYDOWN)
{
if(btClicked!=NULL)
{
btClicked->assigned_key = SDL_GetKeyName(evt.key.keysym.sym);//breakpoint here
btClicked = NULL;
}
下面可以看到断点调试。所有先前分配给 btClicked 的按钮都已更改。但是 btClicked 只是指向其中一个按钮。 The breakpoint Debug
有人知道这里发生了什么吗?请帮忙。
SDL_GetKeyName
的return值指向的字符串只保证在下一次调用SDL_GetKeyName
之前有效。在这种情况下,看起来它有一个静态缓冲区,每次调用都会重复使用该缓冲区,因此您的所有 Button
最终都指向同一个字符串。这意味着如果您需要它保持有效更长时间,您需要复制该字符串。
实现此目的的最简单方法是让您的 Button::assigned_key
成员成为 std::string
而不是原始 const char*
.
无论如何,这几乎总是一个好主意,因为在对象中保留 const char*
成员会混淆所有权语义,并使应用程序更容易出现此类错误和内存泄漏。