不能在块范围内使用 SDL2 变量

Can't use SDL2 variables in Block scope

我正在用SDL2编程,但我无法理解以下背后的原因。这有效:

SDL_Window  *window;
SDL_Surface *screen_surface;
SDL_Surface *picture;

auto initWindow(void)
{…}
auto loadMedia(void)
{…}
auto close(void)
{…}

int main(void)
{
    initWindow();
    loadMedia();
    …
    close();
}

然而这不是:

auto initWindow(SDL_Window *window, SDL_Surface *screen_surface)
{…}
auto loadMedia(SDL_Surface *picture, std::string resource)
{…}
auto close(SDL_Window *window, SDL_Surface *picture)
{…}

int main(void)
{
    SDL_Window  *window;
    SDL_Surface *screen_surface;
    SDL_Surface *picture;
    initWindow(window, screen_surface);
    loadMedia(picture, "resource_file.bmp");
    …
    close(window, picture);
}

唯一的区别是我将 windowscreen_surfacepicture 文件范围 中取出并放入 块范围(即主函数),而不是在这些函数中引用全局变量,我使用参数。 但是,当我尝试 运行 时,它会显示白屏,但不会显示任何错误。我不明白这里出了什么问题。

免责声明:我从来没有做过任何 SDL 编程,所以这只是一个基于常识和我从评论中看到的答案。

假设您的 initWindow 函数为 window 变量设置了一些值。当该变量在全局范围内声明时,使用该变量的所有其他函数也会看到对其的修改。

当您将该变量更改为函数参数时,情况会发生巨大变化。根据您提供的代码:

auto initWindow(SDL_Window *window, SDL_Surface *screen_surface)
{
    window = SDL_GetWindow(); /* or something */
}

int main(void)
{
    SDL_Window  *window;
    SDL_Surface *screen_surface;
    initWindow(window, screen_surface);
    /* some other code that uses 'window' */
}

只有initWindow中的window实际设置为SDL_GetWindow的值。 main 中的 window 变量没有改变:所有其他需要在 main 中使用它的函数将访问一个未初始化的变量,这是未定义的行为。你也有资源泄漏,因为你现在永远无法释放你从 SDL_GetWindow 得到的东西。 initWindow 实际上收到了 window 副本 ,与 main 中的 window 完全无关。

看看您是如何使用 C++ 的,最好的解决方法是让 initWindow 接受对 window 变量的引用,如下所示:

auto initWindow(SDL_Window *&window, SDL_Surface *&screen_surface)
{
    window = SDL_GetWindow(); /* or something */
}

int main(void)
{
    SDL_Window  *window;
    SDL_Surface *screen_surface;
    initWindow(window, screen_surface);
    /* some other code that uses 'window' */
}

现在,main 中的 window 变量将更新为 initWindow 对其所做的操作,以及稍后在 main 中使用 window 的代码将访问通过 SDL_GetWindow.

获取的资源

但是,C++ 允许您通过使用构造函数和析构函数以更有效的方式管理资源,这个概念称为 RAII(资源获取即初始化)。寻找 SDL 对象周围的 C++ 包装器,这将使您的生活更轻松,如果您不这样做,请花一些时间编写您自己的,或者使它们与 std::unique_ptr(或 std::shared_ptr 一起工作,如果您知道你需要它)。稍后你会感谢自己的。