SDL2 - 如果我的颜色未初始化为私有变量,为什么文本会闪烁?
SDL2 - Why is a text flickering if my color is not initialized as a private variable?
我尝试使用以下代码显示文本:
void Text::display(SDL_Renderer *renderer, int x, int y) {
// pos is an SDL_Rect and font is a TTF_Font
pos.x = pos.w = x;
pos.y = pos.h = y;
SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), color);
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h);
SDL_RenderCopy(renderer, texture, NULL, &pos);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
在我的文本中class。起初,我的 Text::display()
方法中有一个未初始化的 SDL_Color color
,它让我在屏幕上显示文本。 (renderer
是从主+坐标x,y
传过来的)。但我决定让我的 SDL_Color color
成为 class Text
中的私有变量。对我来说奇怪的是,作为一个私有变量,一旦我呈现它,文本就会闪烁,但如果我将它设置为 public 变量或将它放在方法中,文本就不会闪烁。或者如果我将它初始化为私有变量 (SDL_Color color = {255, 255, 255}
).
我的问题是当color
未初始化为public或方法变量时是否只是纯粹的运气,或者它们是否被处理不同?当我在构造函数中初始化颜色时,如果颜色是私有的,它也会闪烁。
我的主要方法:
void fpsCap(Uint32 starting_tick) {
if ((1000 / fps) > SDL_GetTicks() - starting_tick) {
SDL_Delay(1000 / fps - (SDL_GetTicks() - starting_tick));
}
}
int main(int argv, char** args) {
// Create renderer, window, etc
while (true) {
SDL_RenderClear(renderer);
Text *txt = new Text("hello");
txt->display(gui->getRenderer(), 0, 0);
SDL_RenderPresent(renderer);
}
}
私有成员的值没有初始化,所以得到random/garbage值。当您为每一帧分配新的 Text 实例时。你在堆上分配(每次都在一个新的地方),所以它实际上是垃圾。
为什么其他情况下不闪烁?
Public 会员:我猜你也是静态的?静态变量是零初始化的(与成员变量相反)。
局部变量:局部变量不归零并被认为包含垃圾,但由于它们是堆栈分配的,它们很可能在给定位置每次都得到相同的垃圾。
构造函数中分配的私有成员:这是意外的。您确定实际使用的是同一个构造函数吗?那是同一个变量吗?也许某些名称隐藏阻止了该值实际到达我们应该到达的位置?
切线:
您在每个循环中都泄漏了一个 Text 实例。您应该 delete
每个使用 new
创建的对象,或者更好的是,完全避免使用 new
。使用 unique_ptr/make_unique 代替,或仅使用局部变量(在这种情况下更好)。
编辑以回答有关 new
的问题:
在现代 C++ 中,您几乎不需要使用 new
.
如果你有一个只在函数执行期间使用的对象,自然的做法是直接保留它(即不通过指针),在这种情况下定义变量作为
Text txt("hello");
这与 Java 的 Text txt = new Text("hello");
类似,但结果变量是一个实例本身,而不是对它的引用。
- 如果你想创建一个你立即作为
Text
或 const Text&
类型参数传递的实例,你可以像 SomeFunction(Text("hello"))
一样临时创建它(注意缺少new
,就是class的名字)。
如果需要堆分配,智能指针(std::unique_ptr
and std::shared_ptr
) created with std::make_unique
and std::make_shared
是
强烈推荐,因为它们可以防止许多常见的陷阱,例如内存泄漏和悬空指针,至少只要您保留智能指针本身。 std::shared_ptr
可能是标准 C++ 最接近 Java 引用的东西,尽管它不是垃圾收集器,所以如果你对它们进行循环,它们将永远不会被释放。
您可以将 Text *txt = new Text("hello");
替换为
auto txt = std::make_unique<Text>("hello");
获得相同的行为,但 Text
在块的末尾被销毁和释放。
我尝试使用以下代码显示文本:
void Text::display(SDL_Renderer *renderer, int x, int y) {
// pos is an SDL_Rect and font is a TTF_Font
pos.x = pos.w = x;
pos.y = pos.h = y;
SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), color);
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h);
SDL_RenderCopy(renderer, texture, NULL, &pos);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
在我的文本中class。起初,我的 Text::display()
方法中有一个未初始化的 SDL_Color color
,它让我在屏幕上显示文本。 (renderer
是从主+坐标x,y
传过来的)。但我决定让我的 SDL_Color color
成为 class Text
中的私有变量。对我来说奇怪的是,作为一个私有变量,一旦我呈现它,文本就会闪烁,但如果我将它设置为 public 变量或将它放在方法中,文本就不会闪烁。或者如果我将它初始化为私有变量 (SDL_Color color = {255, 255, 255}
).
我的问题是当color
未初始化为public或方法变量时是否只是纯粹的运气,或者它们是否被处理不同?当我在构造函数中初始化颜色时,如果颜色是私有的,它也会闪烁。
我的主要方法:
void fpsCap(Uint32 starting_tick) {
if ((1000 / fps) > SDL_GetTicks() - starting_tick) {
SDL_Delay(1000 / fps - (SDL_GetTicks() - starting_tick));
}
}
int main(int argv, char** args) {
// Create renderer, window, etc
while (true) {
SDL_RenderClear(renderer);
Text *txt = new Text("hello");
txt->display(gui->getRenderer(), 0, 0);
SDL_RenderPresent(renderer);
}
}
私有成员的值没有初始化,所以得到random/garbage值。当您为每一帧分配新的 Text 实例时。你在堆上分配(每次都在一个新的地方),所以它实际上是垃圾。
为什么其他情况下不闪烁?
Public 会员:我猜你也是静态的?静态变量是零初始化的(与成员变量相反)。
局部变量:局部变量不归零并被认为包含垃圾,但由于它们是堆栈分配的,它们很可能在给定位置每次都得到相同的垃圾。
构造函数中分配的私有成员:这是意外的。您确定实际使用的是同一个构造函数吗?那是同一个变量吗?也许某些名称隐藏阻止了该值实际到达我们应该到达的位置?
切线:
您在每个循环中都泄漏了一个 Text 实例。您应该 delete
每个使用 new
创建的对象,或者更好的是,完全避免使用 new
。使用 unique_ptr/make_unique 代替,或仅使用局部变量(在这种情况下更好)。
编辑以回答有关 new
的问题:
在现代 C++ 中,您几乎不需要使用 new
.
如果你有一个只在函数执行期间使用的对象,自然的做法是直接保留它(即不通过指针),在这种情况下定义变量作为
Text txt("hello");
这与 Java 的
Text txt = new Text("hello");
类似,但结果变量是一个实例本身,而不是对它的引用。- 如果你想创建一个你立即作为
Text
或const Text&
类型参数传递的实例,你可以像SomeFunction(Text("hello"))
一样临时创建它(注意缺少new
,就是class的名字)。 如果需要堆分配,智能指针(
std::unique_ptr
andstd::shared_ptr
) created withstd::make_unique
andstd::make_shared
是 强烈推荐,因为它们可以防止许多常见的陷阱,例如内存泄漏和悬空指针,至少只要您保留智能指针本身。std::shared_ptr
可能是标准 C++ 最接近 Java 引用的东西,尽管它不是垃圾收集器,所以如果你对它们进行循环,它们将永远不会被释放。您可以将
Text *txt = new Text("hello");
替换为auto txt = std::make_unique<Text>("hello");
获得相同的行为,但
Text
在块的末尾被销毁和释放。