2015-10-06 75 views
1

我得到奇怪的錯誤,試圖通過自定義deletor到std :: shared_ptr的: - 在有任何東西做與它的情況下>unsigned char*的std :: shared_ptr的Deletor類型

std::shared_ptr<unsigned char*> SDLWindow::drawGrid(const Grid* grid) { 
    SDL_Surface* rgbSurface = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGB888, 0); 
    //...error checking and locking the SDL_Surface, omitted for brevity 
    unsigned char* pixelsPtr = (unsigned char*)(rgbSurface->pixels); 

    //need a custom deleter because we created a copy of the SDL_Surface 
    //we cant directly delete the pixel data but need to delete the underlying SDL_Surface instead 
    auto surfaceDeleter = [rgbSurface](decltype(pixelsPtr)* ignored) 
      //don't directly delete the pixel buffer, delete the underlying SDL_Surface instead 
      { 
       //unlock the surface if necessary 
       if(SDL_MUSTLOCK(rgbSurface)) 
       { 
        SDL_UnlockSurface(rgbSurface); 
       } 
       SDL_FreeSurface(rgbSurface); 
      }; 
    return std::shared_ptr<unsigned char*>(pixelsPtr, surfaceDeleter); 
} 

(我改變const unsigned char*但我寧願儘可能使用常量)

鏘說,有關不能夠轉化爲nullptr_t,我以爲是關係到shared_ptrs如何使用類型擦除(但爲什麼不應該他們能夠處理的指針? )

unsigned char* pixelsPtr = (unsigned char*)(rgbSurface->pixels); 
[..]/src/SDLWindow.cpp:132:12: error: no matching constructor for initialization of 'std::shared_ptr<unsigned char *>' 
    return std::shared_ptr<unsigned char*>(pixelsPtr, surfaceDeleter); 
     ^        ~~~~~~~~~~~~~~~~~~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3809:26: note: candidate constructor [with _Dp = (lambda at 
     /[..]/src/SDLWindow.cpp:122:27)] not viable: no known conversion from 'unsigned char *' to 'nullptr_t' for 1st argument 
    template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d); 

奇怪的是G ++似乎給了一個完全不同的錯誤:

    from /[..]/src/SDLWindow.hpp:4, 
       from /[..]/src/SDLWindow.cpp:1: 
/opt/local/include/gcc49/c++/bits/shared_ptr_base.h: In instantiation of 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter) [with _Tp1 = unsigned char; _Deleter = jakway_antf::SDLWindow::drawGrid(const jakway_antf::Grid*)::<lambda(unsigned char**)>; _Tp = unsigned char*; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]': 
/opt/local/include/gcc49/c++/bits/shared_ptr.h:130:37: required from 'std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter) [with _Tp1 = unsigned char; _Deleter = jakway_antf::SDLWindow::drawGrid(const jakway_antf::Grid*)::<lambda(unsigned char**)>; _Tp = unsigned char*]' 
/[..]/src/SDLWindow.cpp:132:69: required from here 
/opt/local/include/gcc49/c++/bits/shared_ptr_base.h:881:37: error: cannot convert 'unsigned char*' to 'unsigned char**' in initialization 
    : _M_ptr(__p), _M_refcount(__p, ntf::SDLWindow::drawGrid(const jakway_antf::)) 

至於G ++我不知道發生了什麼事,因爲我受夠了這種參數的拉姆達混亂,並宣佈它unsigned char**沒有按」不要做任何事情。

我已經試過:

  • 與捕獲參數,它似乎並沒有做任何事情(從我從幾個小時前記得了)
  • 鑄造每哪種方式
  • 搞亂用std :: function聲明lambda而不是自動的 ,我相當堅持。
+2

我相信'std :: shared_ptr '應該是'std :: shared_ptr ' – NathanOliver

+0

@NathanOliver Yikes,我真的應該抓住這個。謝謝! – Prime

回答

5

有一個更清潔的方式做你想做的,使用真棒,非常下記錄的共享指針的功能:

// 1 
std::shared_ptr<SDL_Surface> surface_ptr { 
    SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGB888, 0), 
    [](SDL_Surface* p) { 
     if(SDL_MUSTLOCK(p)) 
      SDL_UnlockSurface(p); 
     SDL_FreeSurface(p); 
    } 
}; 

// 2 
std::shared_ptr<unsigned char> pixels = { surface_ptr, surface->pixels }; 

線1個分配表面並將其置於與定製刪除器共享的指針的控制下。

第2行是非常棒的部分。它在使用相同控制塊作爲表面時初始化共享指針以指向像素數據。

這意味着只有當兩個共享指針已被銷燬或重置時,表面纔會被刪除。它是保存引用計數和刪除器的控制塊,因此您不必擔心兩個共享指針指向不同類型 - 第二個指針只是第一個指針的便利外觀。

請注意,您不必捕獲lambda中的任何內容 - shared_ptr爲您執行此操作並將表面地址作爲參數傳遞。

2

std::shared_ptr<unsigned char*>應該是std::shared_ptr<unsigned char>。使用std::shared_ptr<unsigned char*>表示底層指針是unsigned char**,因爲shared_ptr<T>存儲T*。既然你有一個unsigned char*我們要T成爲unsigned char

相關問題