簡単な質問:boost::shared_ptr
を自分で明示的に削除できますか?あなたは今までにすべきですか?
明確に言うと、shared_ptr
が保持しているポインターを削除するつもりはありません。実際のshared_ptr
そのものを意味しました。私はほとんどの人がそれをしないことを提案していることを知っているので、明示的にそれをしても大丈夫かと思っていました。
あなたの質問は明確ではありません。 shared_ptr
を動的に割り当てた場合、いつでもdelete
に許可されます。
しかし、shared_ptr
によって管理されているオブジェクトを削除できるかどうかを尋ねる場合、答えは...です。 shared_ptr::unique
がtrueを返す場合、shared_ptr::reset
を呼び出すと、管理対象オブジェクトが削除されます。ただし、shared_ptr::unique
がfalseを返す場合、そのオブジェクトの所有権を共有しているshared_ptr
sが複数存在することを意味します。この場合、reset
を呼び出すと、参照カウントが1だけ減ります。そのオブジェクトを管理する最後のshared_ptr
がスコープ外になるか、オブジェクトが削除されると、オブジェクトの実際の削除が行われます。それ自体reset
。
編集:
編集後、動的に割り当てられたshared_ptr
の削除について尋ねているようです。このようなもの:
auto sp = new boost::shared_ptr<int>( new int(42) );
// do something with sp
delete sp;
これは許可されており、予想どおりに機能しますが、通常とは異なる使用例です。唯一の注意点は、sp
の割り当てと削除の間に、オブジェクトの所有権を共有する別のshared_ptr
を作成した場合、sp
を削除してもオブジェクトは削除されないことです。これは、オブジェクトの参照カウントが0になったときにのみ発生します。
[編集:delete
a _shared_ptr
_は、new
で作成された場合に限り、他のタイプと同じことができます。なぜnew
で_shared_ptr
_を作成するのか考えられませんが、あなたを止めるものは何もありません。]
さて、あなたはcoulddelete ptr.get();
と書きます。
そうすることで、other共有所有者が_shared_ptr
_を使用して削除されたオブジェクトにアクセスするか、オブジェクトの最後の_shared_ptr
_が破棄される場合、ほとんどの場合、未定義の動作につながります。オブジェクトが再び削除されます。
いいえ、そうすべきではありません。
_shared_ptr
_の目的は、所有権を共有する他の人が存在する可能性があるため、誰も削除する権利または責任を持たないオブジェクトを管理することです。だから、あなたもしたくないはずです。
参照カウントをゼロに強制することはできません、いいえ。
それが機能するために何が必要かを考えてください。 shared_ptrが使用されている各場所に移動し、クリアする必要があります。
共有ポインターを強制的に削除してNULLに設定した場合、weak_ptrのようになります。ただし、そのshared_ptrを使用するコード内のこれらの場所はすべて、その準備ができておらず、有効なポインターを保持していることを期待しています。 NULLをチェックする理由がないため、これらのコードはクラッシュします。
カウントの減少をシミュレートする場合は、次のようにヒープで手動で実行できます。
_int main(void) {
std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test")));
std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp);
delete sp;
std::cout << *(*sp2) << std::endl; // test
return 0;
}
_
または、次のようにstd::shared_ptr::reset()
を使用してスタック上で:
_int main(void) {
std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test"));
std::shared_ptr<std::string> p2 = p;
p.reset();
std::cout << *p2 << std::endl; // test
return 0;
}
_
しかし、それはそれほど有用ではありません。
いくつかの(非常に?)まれなケースでは、明示的な削除が便利です。
明示的に削除することに加えて、共有ポインタを「削除」するときに明示的に破棄する必要がある場合があります。
Shared_ptrを不透明な値として渡して、Cコードとインターフェースをとると、物事が奇妙になります。
たとえば、Cで記述されたLuaスクリプト言語との間でオブジェクトを渡すために次のものがあります(www.lua.org)
static void Push( lua_State *L, std::shared_ptr<T> sp )
{
if( sp == nullptr ) {
lua_pushnil( L );
return;
}
// This is basically malloc from C++ point of view.
void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>));
// Copy constructor, bumps ref count.
new(ud) std::shared_ptr<T>( sp );
luaL_setmetatable( L, B::class_name );
}
これは、いくつかのmallocされたメモリ内のshared_ptrです。その逆は...(Luaガベージがオブジェクトを収集して「解放」する直前に呼び出されるセットアップ)。
static int destroy( lua_State *L )
{
// Grab opaque pointer
void* ud = luaL_checkudata( L, 1, B::class_name );
std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud);
// Explicitly called, as this was 'placement new'd
// Decrements the ref count
sp->~shared_ptr();
return 0;
}