无效的应用程序,对不完整类型'SDL_Window'使用'sizeof'。

8

当创建一个指向SDL_Window结构体的指针并将其分配给shared_ptr时,会出现上述错误。

类的一部分:

#include <SDL2/SDL.h>

class Application {
    static std::shared_ptr<SDL_Window> window;
}

定义:

#include "Application.h"
std::shared_ptr<SDL_Window> Application::window{};

bool Application::init() {  
    SDL_Window *window_ = nullptr;
    if((window_ = SDL_CreateWindow(title.c_str(),
                                  SDL_WINDOWPOS_UNDEFINED,
                                  SDL_WINDOWPOS_UNDEFINED,
                                  window_width,
                                  window_height,
                                  NULL)
        ) == nullptr) {
        std::cerr << "creating window failed: " << SDL_GetError() << std::endl;
    }

    window.reset(window_);
}

错误出现在'window.reset()'。这是什么原因,如何修复这种行为?

1
也许不相关,但是你不是应该使用SDL_DestroyWindow来释放内存,而不是delete吗? - PlasmaHH
2个回答

10

默认情况下,shared_ptr会使用delete释放管理的资源。然而,如果您正在使用需要以其他方式释放的资源,则需要自定义删除器:

window.reset(window_, SDL_DestroyWindow);

注意:我相当确定这会起作用,但我没有SDL安装来测试它。


@vmrob:抱歉,那是一个笔误,我是指 SDL_DestroyWindow 函数。函数指针应该足够了,不必将它包装在类中。 - Mike Seymour

8

如之前由Mike所说,您需要使用shared_ptr指定删除器。然而,对于unique_ptr,您可能希望创建一个特殊类型的删除器,以便它可以干净地用作模板参数。我使用了这个结构体:

struct SDLWindowDeleter {
    inline void operator()(SDL_Window* window) {
        SDL_DestroyWindow(window);
    }
};

然后通过模板参数包含删除器:
std::unique_ptr<SDL_Window, SDLWindowDeleter> sdlWindowPtr = SDL_CreateWindow(...);

不需要像那样将函数调用包装在类中。删除器可以是任何适当的可调用对象,包括指向SDL_DestroyWindow的指针。 - Mike Seymour
如果你要使用std::unique_ptr,那么你需要一个类型而不是函数指针,对吗? - vmrob
2
抱歉,我没有注意到你已经转移到了 unique_ptr。它也可以接受任何适当的可调用对象,包括函数指针。这会稍微有些混乱,因为在实例化模板时需要显式指定删除器类型(即 std::unique_ptr<SDL_Window, void(*)(SDL_Window*)>),所以自定义类类型可能更加整洁。 - Mike Seymour
@MikeSeymour 真的吗?我之前不知道这个。每天都在学习新东西!现在看起来,这很有道理。我认为使用自定义类型可以消除运行时开销,因为编译器可以内联函数调用,这也是建议的做法。 - vmrob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接