46

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ドキュメントを見てきましたが、あまり意味がありません。私は何が間違っているのですか?

編集:それ以来、問題を絞り込みましたが、元の質問は上に残しておきます。私が持っていたのはゲームクラスでした。これを基本的な実装に分解すると、次のようになります。

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

4

2 に答える 2

63
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::bindますstd::mem_fn

于 2012-09-09T16:35:14.447 に答える
10

このコードは、オブジェクトメソッドとしてdeleterを使用した共有ポインター構造の例を示しています。使用説明書を表示std::bindします。

例は単純なオブジェクトリサイクラーです。オブジェクトへの最後の参照が破棄されると、オブジェクトはリサイクラー内の空きオブジェクトプールに戻されます。

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));
    }
}
于 2015-04-17T14:17:48.110 に答える