回答:
これは、std::shared_ptr
型消去を実装しているのに対し、実装してstd::unique_ptr
いないためです。
std::shared_ptr
型消去を実装しているため、別の興味深いプロパティ、つまりviz もサポートしています。クラステンプレートへのテンプレートタイプ引数として、削除機能のタイプは必要ありません。彼らの宣言を見てください:
template<class T,class Deleter = std::default_delete<T> >
class unique_ptr;
これは持っていDeleter
ながら、型パラメータとして
template<class T>
class shared_ptr;
それはありません。
今問題は、なぜshared_ptr
型消去を実装するのですか?参照カウントをサポートする必要があるため、そうします。これをサポートするには、ヒープからメモリを割り当てる必要があります。とにかくメモリを割り当てる必要があるため、さらに一歩進んで、型消去(ヒープが必要)を実装します。割り当ても。つまり、基本的には日和見主義者です。
型消去のため、std::shared_ptr
は次の2つをサポートできます。
void*
、まだまだ適切に破壊上のオブジェクトを削除することができ、正しくによって彼らのデストラクタを呼び出します。よし。それがどのようにstd::shared_ptr
機能するかについてのすべてです。
今問題は、std::unique_ptr
オブジェクトを void*
?ええ、答えは、はいです。適切な削除プログラムを引数として渡した場合です。そのようなデモの1つを次に示します。
int main()
{
auto deleter = [](void const * data ) {
int const * p = static_cast<int const*>(data);
std::cout << *p << " located at " << p << " is being deleted";
delete p;
};
std::unique_ptr<void, decltype(deleter)> p(new int(959), deleter);
} //p will be deleted here, both p ;-)
出力(オンラインデモ):
959 located at 0x18aec20 is being deleted
あなたはコメントで非常に興味深い質問をしました:
私の場合、型を削除する削除機能が必要になりますが、それも可能です(ヒープ割り当てを犠牲にして)。基本的に、これは実際には3番目のタイプのスマートポインターのニッチスポットがあることを意味しますか?タイプ消去付きの排他的所有権スマートポインターです。
これに@Steveジェソップは、以下のソリューションを提案し、
私は実際にこれを試したことはありませんが、おそらく
std::function
、unique_ptr
?それが実際に機能するとしたら、あなたは完了し、独占的な所有権と型消去された削除プログラムを実行します。
この提案に従って、私はこれを実装しました(ただし、std::function
必要と思われないため、これを利用していません)。
using unique_void_ptr = std::unique_ptr<void, void(*)(void const*)>;
template<typename T>
auto unique_void(T * ptr) -> unique_void_ptr
{
return unique_void_ptr(ptr, [](void const * data) {
T const * p = static_cast<T const*>(data);
std::cout << "{" << *p << "} located at [" << p << "] is being deleted.\n";
delete p;
});
}
int main()
{
auto p1 = unique_void(new int(959));
auto p2 = unique_void(new double(595.5));
auto p3 = unique_void(new std::string("Hello World"));
}
出力(オンラインデモ):
{Hello World} located at [0x2364c60] is being deleted.
{595.5} located at [0x2364c40] is being deleted.
{959} located at [0x2364c20] is being deleted.
お役に立てば幸いです。
std::function
、デリケーターのタイプとして適切なものを使用することでそれを達成できunique_ptr
ますか?それが実際に機能するとしたら、あなたは完了し、独占的な所有権と型消去された削除プログラムを実行します。
理論的根拠の1つは、aの多くのユースケースの1つにありますshared_ptr
-つまり、寿命インジケーターまたはセンチネルとして。
これは元のブーストのドキュメントで言及されていました:
auto register_callback(std::function<void()> closure, std::shared_ptr<void> pv)
{
auto closure_target = { closure, std::weak_ptr<void>(pv) };
...
// store the target somewhere, and later....
}
void call_closure(closure_target target)
{
// test whether target of the closure still exists
auto lock = target.sentinel.lock();
if (lock) {
// if so, call the closure
target.closure();
}
}
closure_target
このようなものはどこにありますか:
struct closure_target {
std::function<void()> closure;
std::weak_ptr<void> sentinel;
};
呼び出し元は、次のようなコールバックを登録します。
struct active_object : std::enable_shared_from_this<active_object>
{
void start() {
event_emitter_.register_callback([this] { this->on_callback(); },
shared_from_this());
}
void on_callback()
{
// this is only ever called if we still exist
}
};
ので、shared_ptr<X>
常にに変換されshared_ptr<void>
、event_emitterは今、それがバックに呼び出しているオブジェクトの種類の穏やか気づいていないことができます。
この配置により、サブスクライバーがイベントエミッターのクロスケースを処理する義務が解放され(コールバックがキューにある場合、active_objectがなくなるまでアクションが実行されるのを待機していますか?)、サブスクリプションを同期する必要がないことも意味します。weak_ptr<void>::lock
同期操作です。
std::unique_ptr<void, D>
、適切なを提供することでa がまだ可能であることを明示的に言及することで、それをさらに改善することができD
ます。