2013-08-19 19 views
6

Utworzenie wskaźnika do struktury SDL_Window i przypisanie jej do shared_ptr, wymienione wyniki błędu.Nieprawidłowa aplikacja "sizeof" do niekompletnego typu "SDL_Window"

część klasy:

#include <SDL2/SDL.h> 

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

Definicja:

#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_); 
} 

pojawi się błąd w 'window.reset()'. Jaki jest powód i jak naprawić to zachowanie?

+1

Może niepowiązanych, ale czy nie trzeba zwalnianie poprzez SDL_DestroyWindow zamiast usunąć? – PlasmaHH

Odpowiedz

8

Domyślnie shared_ptr zwalnia zarządzany zasób, używając delete. Jednakże, jeśli używasz zwalnianie zasobów, które wymaga innego sposobu, musisz niestandardową Deleter:

window.reset(window_, SDL_DestroyWindow); 

UWAGA: Jestem całkiem pewien, że to będzie działać, ale nie masz SDL instalacja, aby przetestować to przy pomocy.

+0

@vmrob: Przepraszam, to był literówka, miałem na myśli funkcję 'SDL_DestroyWindow'. Wskaźnik funkcji powinien być wystarczający, bez owijania go w klasę. –

7

Jak wcześniej powiedziałem, Mike, musisz podać swój deleter z shared_ptr. Jednak w przypadku modelu unique_ptr prawdopodobnie będziesz chciał utworzyć specjalny typ dla swojego deletera, aby mógł być czysto używany jako parametr szablonu. Użyłem tej struktury:

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

Następnie obejmować Deleter poprzez parametr szablonu:

std::unique_ptr<SDL_Window, SDLWindowDeleter> sdlWindowPtr = SDL_CreateWindow(...); 
+0

Nie ma potrzeby pakowania wywołania funkcji w taką klasę. Deleterem może być dowolny właściwie wywoływalny obiekt, w tym wskaźnik do 'SDL_DestroyWindow'. –

+0

Jeśli jednak używasz go z 'std :: unique_ptr', musisz mieć typ, w przeciwieństwie do wskaźnika funkcji, prawda? – vmrob

+2

Niestety, nie zauważyłem, że zagłębiłeś się w 'unique_ptr'. Może to również zająć dowolny obiekt, który można odpowiednio wywołać, w tym wskaźnik funkcji. Byłoby to nieco bardziej niepotrzebne, ponieważ musiałbyś jawnie określić typ narzędzia podczas tworzenia szablonu (np. 'Std :: unique_ptr ), więc niestandardowy typ klasy może być schludniej. –