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
Using custom deleter with std::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类之外而不更改它,则代码会编译。DeleteSurface在Game导致问题的类中包含函数是什么意思?
回答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::bind或std::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));
}
}

