在std :: shared_ptr中使用自定义删除器

时间:2012-09-09 16:32:40

标签: c++ shared-ptr

我正在尝试研究如何将std :: shared_ptr与自定义删除器一起使用。具体来说,我将它与SDL_Surface一起用作:

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface);

编译并运行正常。但是,我想尝试自己的删除器,但无法知道如何操作。 SDL_FreeSurface的文档可在此处找到:

http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface

我发现SDL_FreeSurface被声明为:

void SDL_FreeSurface(SDL_Surface* surface);

作为测试,并通过该信息,我尝试了以下功能:

void DeleteSurface(SDL_Surface* surface)
{
    std::cout << "Deleting surface\n";
    SDL_FreeSurface(surface);
}

但是,用g ++编译会给我带来以下错误:

error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)'

我已经查看了gcc std :: shared_ptr实现的gnu文档,但是对它没有多大意义。我做错了什么?

编辑:我已经缩小了问题的范围,但是会留下上面的原始问题。我所拥有的是一个Game类,如果我把它拆分为一个基本的实现,就像是:

class Game {
    public:
        /* various functions */
    private:
        void DeleteSurface(SDL_Surface* surface);
        bool CacheImages();
        std::vector<std::shared_ptr<SDL_Surface> > mCachedImages;

        /* various member variables and other functions */
}

如上所述DeleteSurface的实施,以及CacheImages()的实施:

bool CacheImages()
{
    mCachedImages.push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface);
    return true;
}

哪个游戏我上面列出的错误。但是,如果我将DeleteSurface()函数移到Game类之外而没有另外修改它,则代码会编译。在DeleteSurface类中包含导致问题的Game函数是什么意思?

2 个答案:

答案 0 :(得分:50)

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), [=](SDL_Surface* surface)
{
    std::cout << "Deleting surface\n";
    SDL_FreeSurface(surface);
});

void DeleteSurface(SDL_Surface* surface)
{
    std::cout << "Deleting surface\n";
    SDL_FreeSurface(surface);
}

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), DeleteSurface);

编辑:

查看更新的问题,DeleteSurface应该是非成员函数,否则您需要使用std::bindstd::mem_fn或其他一些成员函数指针适配器。

答案 1 :(得分:10)

此代码提供了一个以删除器作为对象方法的共享指针构造示例。它显示要使用的std::bind指令。

该示例是一个简单的对象回收器。当销毁对象的最后一个引用时,该对象将返回到回收器内的自由对象池。

通过向get()add()方法添加密钥并将对象存储在std::map中,可以轻松地将recyler更改为对象缓存。

class ObjRecycler
{
private:
    std::vector<Obj*> freeObjPool;
public:
    ~ObjRecycler()
    {
        for (auto o: freeObjPool)
            delete o;
    }

    void add(Obj *o)
    {
        if (o)
            freeObjPool.push_back(o);
    }

    std::shared_ptr<Obj> get()
    {
        Obj* o;
        if (freeObjPool.empty())
            o = new Obj();
        else
        {
            o = freeObjPool.back();
            freeObjPool.pop_back();
        }
        return std::shared_ptr<Obj>(o, 
             std::bind(&ObjRecycler::add, this, std::placeholders::_1));
    }
}