使用自定义删除器创建std::shared_ptr时编译失败求助
问题分析与解决方案
你遇到的编译错误,核心原因是**Window::Deleter的operator()是私有成员**,而std::shared_ptr需要在其内部调用这个删除器的调用运算符,但它没有访问权限。而std::unique_ptr的情况看起来正常,大概率是你在Image::Deleter中不小心把operator()设为了公有(或者编译器的延迟检查暂时没触发错误,但实际上如果operator()是私有,unique_ptr在析构时也会报错)。
为什么shared_ptr会报错,unique_ptr看似正常?
两者对自定义删除器的处理逻辑有本质区别:
std::unique_ptr的删除器是模板参数,它的类型是std::unique_ptr<T, Deleter>。编译器在创建unique_ptr时,可能不会立即检查Deleter::operator()的访问权限,直到实际触发析构(比如unique_ptr离开作用域)。如果你的Image类的Deleter::operator()确实是私有,那后续完整编译或运行时也会报错。std::shared_ptr的删除器不是模板参数,它的类型就是std::shared_ptr<T>,删除器被存储在共享的控制块中。编译器在构造shared_ptr时,就需要确认删除器的operator()是可访问的,否则直接抛出编译错误。
修复方案
最简单且推荐的方法,就是把Deleter的operator()设为公有成员:
class Window:private Uncopyable { public: class Deleter { public: // 新增public修饰符,开放调用权限 void operator()(SDL_Window *window) { SDL_DestroyWindow(window); } }; static const int SCREEN_WIDTH = 800; static const int SCREEN_HEIGHT = 600; std::shared_ptr<SDL_Window> operator()() const { return std::shared_ptr<SDL_Window>( SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN), Deleter()); } };
额外验证
同时建议你检查Image类的Deleter,确保operator()是公有的,避免后续潜在的编译/运行错误:
class Image: private Uncopyable { public: class Deleter{ public: // 新增public修饰符 void operator()(SDL_Surface *image) { SDL_FreeSurface(image); } }; std::unique_ptr<SDL_Surface, Deleter> operator()(const std::string &path) const { return std::unique_ptr<SDL_Surface, Deleter>( IMG_Load(path.c_str()), Deleter()); } };
这样修改后,Window类的shared_ptr构造就能正常编译,和Image类的unique_ptr保持一致的工作逻辑。
内容的提问来源于stack exchange,提问作者dheeraj suthar
相关产品推荐
相关产品推荐

