[解決済み】std::unique_ptr<T>はTの完全な定義を知るために必要なのでしょうか?
質問
ヘッダーに次のようなコードがあります。
#include <memory>
class Thing;
class MyClass
{
std::unique_ptr< Thing > my_thing;
};
このヘッダを含まないcppでインクルードすると
Thing
の型定義は、VS2010-SP1ではコンパイルできません。
1>C:♪Program Files (x86)♪マイクロソフト ビジュアルスタジオ 10.0VCVCludeincludememory(2067): error C2027: use of undefined type 'Thing'
交換
std::unique_ptr
で
std::shared_ptr
と入力すると、コンパイルされます。
ということで、現在のVS2010の
std::unique_ptr
の実装で完全な定義が必要で、完全に実装依存です。
それとも、そうなのか?標準要件で
std::unique_ptr
の実装は、前方宣言のみで動作するのでしょうか?へのポインタを保持するだけでいいはずなのに、不思議な感じがします。
Thing
ということでしょうか?
どのように解決するのですか?
からの採用 こちら .
C++標準ライブラリのほとんどのテンプレートは、完全な型を持ってインスタンス化することを要求しています。しかし
shared_ptr
と
unique_ptr
は
パーシャル
の例外です。そのメンバの一部(すべてではない)は、不完全な型でインスタンス化することができます。その動機は、以下のようなイディオムをサポートするためです。
pimpl
スマートポインタを使用することで、未定義の動作のリスクを回避することができます。
未定義の動作は、不完全な型を持っているときに
delete
を使用します。
class A;
A* a = ...;
delete a;
上記は合法的なコードです。コンパイルできます。コンパイラは上記のようなコードに対して警告を発するかもしれませんし、発しないかもしれません。このコードが実行されると、おそらく悪いことが起こるでしょう。もし、あなたがとても幸運なら、あなたのプログラムはクラッシュするでしょう。しかし、もっとありそうなのは、プログラムが黙ってメモリをリークして
~A()
は呼び出されない。
使用方法
auto_ptr<A>
の例では、役に立ちません。生のポインターを使った場合と同じように、未定義の動作が発生します。
とはいえ、不完全なクラスを特定の場所で使用することはとても便利なことです これは
shared_ptr
と
unique_ptr
のヘルプを参照してください。これらのスマートポインタのいずれかを使用すると、完全な型が必要な場合を除き、不完全な型でも大丈夫になります。そして最も重要なことは、完全な型を持つことが必要なときに、その時点で不完全な型でスマートポインタを使おうとすると、コンパイル時にエラーが発生することです。
未定義の動作がなくなります。
コードがコンパイルされれば、必要な場所で完全な型を使用したことになります。
class A
{
class impl;
std::unique_ptr<impl> ptr_; // ok!
public:
A();
~A();
// ...
};
shared_ptr
と
unique_ptr
は、異なる場所で完全な型を必要とします。理由はよくわからないのですが、動的削除と静的削除に関係するものです。正確な理由は重要ではありません。実際、ほとんどのコードでは、どこで完全な型が必要なのかを正確に知ることは、あまり重要ではありません。ただコードを書けばいいし、もし間違ったらコンパイラが教えてくれる。
しかし、あなたの役に立つかもしれないので、以下の表は
shared_ptr
と
unique_ptr
を、完全性の要件に照らして検討する。メンバーが完全な型を要求している場合、エントリには "C"、それ以外の場合はテーブルエントリに "I" が記入される。
Complete type requirements for unique_ptr and shared_ptr
unique_ptr shared_ptr
+------------------------+---------------+---------------+
| P() | I | I |
| default constructor | | |
+------------------------+---------------+---------------+
| P(const P&) | N/A | I |
| copy constructor | | |
+------------------------+---------------+---------------+
| P(P&&) | I | I |
| move constructor | | |
+------------------------+---------------+---------------+
| ~P() | C | I |
| destructor | | |
+------------------------+---------------+---------------+
| P(A*) | I | C |
+------------------------+---------------+---------------+
| operator=(const P&) | N/A | I |
| copy assignment | | |
+------------------------+---------------+---------------+
| operator=(P&&) | C | I |
| move assignment | | |
+------------------------+---------------+---------------+
| reset() | C | I |
+------------------------+---------------+---------------+
| reset(A*) | C | C |
+------------------------+---------------+---------------+
ポインタの変換を必要とする操作には、以下の両方の完全な型が必要です。
unique_ptr
と
shared_ptr
.
は
unique_ptr<A>{A*}
コンストラクタは、不完全な
A
への呼び出しを設定する必要がない場合に限り、コンパイラは
~unique_ptr<A>()
. 例えば、もしあなたが
unique_ptr
をヒープ上に置くと、不完全な
A
. この点に関する詳細は
BarryTheHatchetの
回答
こちら
.
関連
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み] std::vectorをハードコードされた要素で初期化する最も簡単な方法は何ですか?
-
[解決済み] const std::string & をパラメータとして渡す時代は終わったのでしょうか?
-
[解決済み】std::auto_ptrからstd::unique_ptrへ
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] 配列のベクトルを扱う正しい方法
-
[解決済み] フォワード宣言はどのような場合に使用できますか?
-
[解決済み】std::unique_ptrが不完全な型だとコンパイルされない