[解決済み] shared_ptr<void>は合法で、unique_ptr<void>は不正な形式なのはなぜですか?
疑問点
タイトルの通りの質問です。この違いの技術的な理由は何なのか、またその根拠は何なのか、知りたいと思っています。
std::shared_ptr<void> sharedToVoid; // legal;
std::unique_ptr<void> uniqueToVoid; // ill-formed;
どのように解決するのですか?
それは
std::shared_ptr
は型消去を実装しているのに対し
std::unique_ptr
はそうではありません。
から
std::shared_ptr
は型消去を実装しているので
別の
という興味深い性質も持っています。
ではない
は、削除者の型が必要である。
をテンプレート型引数として
をクラステンプレートに渡す必要があります。それらの宣言を見てください。
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*
, を格納することができますが、破壊時にオブジェクトを適切に削除することができます。 によって、正しく デストラクタを呼び出すことで . - deleterの型はクラステンプレートの型引数として渡されないので、少し自由です 型安全性を損なわずに .
さてさて。以上、どのように
std::shared_ptr
がどのように機能するかについてです。
さて、問題は
std::unique_ptr
オブジェクトを格納する
として
void*
? さて、その答えはというと
です。
- ただし、引数として適切なデレッガを渡すことが条件です。以下はそのようなデモです。
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 番目のタイプのスマート ポインターのためのニッチ スポットが実際に存在することを意味します。
に対して スティーブ・ジェソップ は次のような解決策を提案しました。
実際に試したことはないのですが、もしかしたら適切な
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.
お役に立てれば幸いです。
関連
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] CとC++でmain()は何を返すべきですか?
-
[解決済み] 8192個の要素にループをかけると、プログラムが遅くなるのはなぜですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
-
[解決済み] std::shared_ptr<void>はなぜ動くのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】'std::cout'への未定義の参照