我在尝试将自定义deletor传递给std :: shared_ptr时遇到了奇怪的错误:
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*
- &gt; unsigned char*
,如果与它有任何关系,但我希望尽可能使用const)
Clang说不能转换为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 ++,我不知道发生了什么,因为我已经搞乱了lambda的参数并声明unsigned char**
没有做任何事情。
我试过了:
答案 0 :(得分:5)
使用共享指针的一个非常棒且记录不足的功能,有一种更清洁的方式来做你想要的事情:
define_singleton_method
第1行分配表面并将其置于具有自定义删除器的共享指针的控制之下。
第2行是很棒的部分。它使用相同的控制块作为表面,初始化一个指向像素数据的共享指针。
这意味着只有在两个共享指针都被销毁或重置时才会删除曲面。它是控制块,它保存引用计数和删除器,因此您不必担心两个共享指针指向不同的类型 - 第二个只是第一个方便的外观。
请注意,您不必捕获lambda中的任何内容 - shared_ptr会为您执行此操作并将表面地址作为参数传递。
答案 1 :(得分:3)
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