あなたの提案で
その後、クライアントはカウンターをデクリメントする責任があります。
問題のクライアントがメモリ管理に責任があり、あなたが彼女を信頼していることを意味します。理由はまだわかりません。
shared_ptrカウンターを実際に変更することはできません...(うーん、最後にその方法を説明します...)が、他の解決策があります。
解決策1:クライアントに対する完全な所有権
クライアントへのポインタ(shared_ptr :: release)を渡し、コールバックするときに所有権が返されることを期待します(または、実際に共有されていない場合は単にオブジェクトを削除します)。
これは、生のポインタを処理するときの実際の従来のアプローチであり、ここでも適用されます。欠点は、実際にはこのshared_ptrの所有権のみを解放することです。オブジェクトが実際に共有されている場合、それは不便であることがわかるかもしれません...だから私に耐えてください。
解決策2:コールバックを使用
このソリューションは、常に所有権を維持し、クライアントが必要とする限り、このオブジェクトを存続させる(そしてキックする)責任があることを意味します。クライアントがオブジェクトの処理を終えたら、クライアントがそのように指示し、必要なクリーンアップを実行するコールバックをコードで呼び出すことを期待します。
struct Object;
class Pool // may be a singleton, may be synchronized for multi-thread usage
{
public:
int accept(boost::shared_ptr<Object>); // adds ptr to the map, returns NEW id
void release(int id) { m_objects.erase(id); }
private:
std::map< int, boost::shared_ptr<Object> > m_objects;
}; // class Pool
このように、クライアントがカウンターを「デクリメント」するのは、実際には、使用したIDでコールバックメソッドを呼び出すクライアントであり、1つのshared_ptrを削除します:)
boost::shared_ptrをハッキングする
私が言ったように、(C ++を使用しているので)実際にshared_ptrにハッキングすることは可能です。それを行うにはいくつかの方法があります。
最良の(そして最も簡単な)方法は、ファイルを別の名前(my_shared_ptr?)でコピーしてから、次のようにすることです。
- インクルードガードを変更する
- 最初に実際のshared_ptrを含めます
- shared_ptrのインスタンスの名前を自分の名前に変更します(属性にアクセスするには、privateをpublicに変更します)
- 衝突を避けるために、実際のファイルですでに定義されているものをすべて削除します
このようにして、カウントにアクセスできる独自のshared_ptrを簡単に取得できます。ただし、Cコードがカウンターに直接アクセスするという問題は解決されませんが、ここでコードを「単純化」して、組み込みのコードに置き換える必要がある場合があります(マルチスレッドでない場合は機能し、まったく悲惨です)。あなたがいる場合)。
'reinterpret_cast'トリックを意図的に省略し、ポインターがそれらをオフセットします。C / C ++で何かに不正にアクセスする方法はたくさんあります!
ただし、ハックを使用しないようにアドバイスしてもいいですか?上で示した2つの解決策は、問題に取り組むのに十分なはずです。