You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用自定义删除器创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:37:05