C++ 将自定义删除器与 std::shared_ptr 一起使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12340810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:11:44  来源:igfitidea点击:

Using custom deleter with std::shared_ptr

c++shared-ptr

提问by Wheels2050

I'm trying to work out how to use std::shared_ptr with a custom deleter. Specifically, I'm using it with SDL_Surface as:

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

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

which compiles and runs fine. However, I would like to try out my own deleter and cannot work out how to do so. The documentation for SDL_FreeSurface is found here:

它编译并运行良好。但是,我想尝试一下自己的删除器,但不知道该怎么做。SDL_FreeSurface 的文档可以在这里找到:

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

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

in which I find the SDL_FreeSurface is declared as:

在其中我发现 SDL_FreeSurface 被声明为:

void SDL_FreeSurface(SDL_Surface* surface);

As a test, and going by that information, I tried the following function:

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

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

However, compiling with g++ gives me the following error:

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

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

I have looked at the gnu documentation for the gcc std::shared_ptr implementation but cannot make much sense of it. What am I doing wrong?

我已经查看了 gcc std::shared_ptr 实现的 gnu 文档,但无法理解它。我究竟做错了什么?

EDIT: I've since narrowed down the problem, but will leave the original question above. What I had was a Game class which, if I strip it down to a basic implementation, was something like:

编辑:我已经缩小了问题的范围,但会保留上面的原始问题。我拥有的是一个 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 */
}

with the implementation of DeleteSurfaceas above, and the implementation of CacheImages()as:

与上述的实施DeleteSurface,并实施CacheImages()为:

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

which game me the error I listed above. However, if I move the DeleteSurface()function outside the Gameclass without otherwise altering it, the code compiles. What is it about including the DeleteSurfacefunction in the Gameclass that is causing problems?

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

回答by ronag

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

or

或者

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

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

EDIT:

编辑:

Seeing your updated question, DeleteSurfaceshould be a non-member function, otherwise you need to use std::bindor std::mem_fnor some other member function pointer adapter.

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

回答by chmike

This code provides an example of a shared pointer construction with the deleter as an object method. It display the std::bindinstruction to use.

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

The example is a simple object recycler. When the last reference to the object is destroyed, the object is returned to the free object pool inside the recycler.

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

The recyler can be easily changed into an object cache by adding a key to the get()and add()methods and by storing the objects in a std::map.

通过向get()add()方法添加键并将对象存储在std::map.

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));
    }
}