是否可以将SDL2与智能指针一起使用



我有这条代码

//std::unique_ptr<SDL_Window> _window_; // this is somewhere else...
_window_ = std::make_unique<SDL_Window>(SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _WIDTH_, _HEIGHT_, SDL_WINDOW_SHOWN));

它产生以下编译器错误

In file included from /usr/include/c++/6/memory:81:0,
                 from /home/user/prj/src/main.cpp:4:
/usr/include/c++/6/bits/unique_ptr.h: In instantiation of ‘typename 
std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = SDL_Window; _Args = {SDL_Window*}; typename 
std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<SDL_Window>]’:
/home/user/prj/src/main.cpp:36:170:   required from here
/usr/include/c++/6/bits/unique_ptr.h:791:30: error: invalid use of incomplete type ‘struct SDL_Window’
     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

为什么?(没有明智的指针,它可以正常工作,所以我的猜测是我不了解该语法,这是很微不足道的。将在下面添加源和CMakeLists.txt。(

cmakelists.txt

cmake_minimum_required(VERSION 3.7)
project(prj)
find_package(SDL2 REQUIRED)
include_directories(prj ${SDL2_INCLUDE_DIRS})
add_executable(prj main.cpp)
target_link_libraries(prj ${SDL2_LIBRARIES})

main.cpp

#include "SDL.h"
#include <memory>
#include <iostream>
#include <fstream>
#include <cstdint>
class Window
{
    public:
    Window()
        : _window_{nullptr}
        , _surface_{nullptr}
    {
        if(SDL_Init(SDL_INIT_VIDEO) < 0)
        {
            std::cerr << SDL_GetError() << std::endl;
        }
        else
        {
            _window_ = std::make_unique<SDL_Window>(SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _WIDTH_, _HEIGHT_, SDL_WINDOW_SHOWN));
            if(_window_ == nullptr)
            {
                std::cerr << SDL_GetError() << std::endl;
            }
            else
            {
                _surface_ = std::make_unique<SDL_Surface>(SDL_GetWindowSurface(_window_.get()));
                SDL_FillRect(_surface_.get(), nullptr, SDL_MapRGB(_surface_->format, 0xFF, 0xFF, 0xFF));
                SDL_UpdateWindowSurface(_window_.get());
                SDL_Delay(1000);
            }
        }
    }
    ~Window()
    {
        SDL_DestroyWindow(_window_.get());
        SDL_Quit();
    }
    private:
    const int32_t _WIDTH_{600};
    const int32_t _HEIGHT_{400};
    std::unique_ptr<SDL_Window> _window_;
    std::unique_ptr<SDL_Surface> _surface_;
};

int main(int argc, char* argv[])
{
    Window window;
    return 0;
}

解决方案

最终通过大量反复试验弄清楚了答案,因此可以在此处解释解决方案。

这是正确的语法:

// first define the unique_ptr as member of class
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> _window_;
// second, initialize in the member initialization list of class constructor
// probably don't need to do this if not embedding as member of class
class_name()
    : _window_(nullptr, SDL_DestroyWindow)
{
    // blaa blaa SDL code etc
    _window_.reset(SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN));
}
// finally we need to be able to delete
// but this is handled automatically

说明

当我们添加solution_ptr作为数据成员时,我们需要同时给出类型SDL_Window和" deleter函数格式/语法",因为普通delete调用不正确。我们使用decltype自动从DELETER函数构造正确的DELERE格式。(也许不是最准确的解释。(在某种程度上,decltype有点像自动...

std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> _window_;

必须初始化此对象。我们在构造函数中这样做。我们将指针设置为nullptr(因为我们不想在初始化SDL2之前初始化它(,并且还设置了Deleter函数。

: _window_(nullptr, SDL_DestroyWindow)

初始化SDL后,我们要创建一个窗口。通过调用智能指针reset()函数来完成此操作。我们通过它通过了创建窗口的函数返回的新指针。

_window_.reset(SDL_CreateWindow(...));

完成。花了很长时间才弄清楚,但现在很有意义。参考

http://en.cppreference.com/w/cpp/memory/unique_ptr

为什么我的unique_ptr认为是一个null函数指针deleter?

unique_ptr的初始化是什么问题?

这些结构是不透明的数据结构,您没有它们的完整定义。这意味着,除其他外,默认的std::unique_ptr DELERER不知道如何"删除"结构。

您需要提供自己的自定义deleter。对于SDL_Window,这是SDL_DestroyWindow函数。

使用sdl_destroywindow而不是普通删除,sdl窗口被销毁,就像unique_ptr的默认deleter一样。您需要向unique_ptr提供自定义deleter,该_ptr将调用sdl_destroywindow。

相关内容

  • 没有找到相关文章

最新更新