2013-08-19 58 views
6

Tạo con trỏ tới cấu trúc SDL_Window và gán nó cho shared_ptr, kết quả lỗi được đề cập.Ứng dụng không hợp lệ 'sizeof' vào loại không đầy đủ 'SDL_Window'

Một phần của lớp:

#include <SDL2/SDL.h> 

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

Định nghĩa:

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

Lỗi xuất hiện ở 'window.reset()'. Lý do và cách khắc phục hành vi này là gì?

+1

Có lẽ không liên quan, nhưng bạn không cần phải deallocate qua SDL_DestroyWindow thay vì xóa? – PlasmaHH

Trả lời

8

Theo mặc định, shared_ptr sẽ giải phóng tài nguyên được quản lý bằng cách sử dụng delete. Tuy nhiên, nếu bạn đang sử dụng một nguồn lực mà cần giải phóng một cách khác, bạn sẽ cần một deleter tùy chỉnh:

window.reset(window_, SDL_DestroyWindow); 

LƯU Ý: Tôi khá chắc chắn điều này sẽ làm việc, nhưng tôi không có một SDL cài đặt để kiểm tra nó với.

+0

@vmrob: Xin lỗi, đó là lỗi đánh máy, tôi có nghĩa là chức năng 'SDL_DestroyWindow'. Con trỏ hàm phải đủ, không cần gói nó trong một lớp. –

7

Như đã nói trước đây bởi Mike, bạn sẽ phải chỉ định deleter của mình với shared_ptr. Tuy nhiên, đối với một unique_ptr, bạn có thể muốn tạo một kiểu đặc biệt cho deleter của bạn để nó có thể được sử dụng một cách rõ ràng làm tham số mẫu. Tôi sử dụng struct này:

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

Sau đó, bao gồm các deleter qua mẫu tham số:

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

Không cần phải gọi hàm trong một lớp như thế. Deleter có thể là bất kỳ đối tượng nào có thể gọi thích hợp, bao gồm một con trỏ tới 'SDL_DestroyWindow'. –

+0

Nếu bạn sử dụng nó với một 'std :: unique_ptr', bạn sẽ cần một kiểu như trái ngược với một con trỏ hàm, đúng không? – vmrob

+2

Xin lỗi, tôi không nhận thấy rằng bạn đã bị rút gọn thành 'unique_ptr'. Điều đó cũng có thể lấy bất kỳ đối tượng nào có thể gọi được, bao gồm cả một con trỏ hàm. Nó sẽ hơi lộn xộn hơn, vì bạn cần xác định rõ ràng loại deleter khi tạo mẫu (ví dụ: 'std :: unique_ptr '), do đó, một loại lớp tùy chỉnh có thể là neater. –