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"); 类似,但结果变量是一个实例本身,而不是对它的引用。

  • 如果你想创建一个你立即作为 Textconst 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 在块的末尾被销毁和释放。