2015-10-06 77 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

相关问题