[解決済み] c++でオブジェクトを初期化するさまざまな方法
質問
このクラスを想像してください。
class Entity {
public:
int x, y;
Entity() : x(0), y(0) { }
Entity(int x, int y) : x(x), y(y) { }
}
そして、私が知っていると思うものでクラスを初期化する複数の方法を紹介します。
Entity ent1; //Uses the default constructor, so x=0 and y=0
Entity ent2(); //Uses the default constructor, so x=0 and y=0 (Not sure)
Entity ent3(1, 2); //Made constructor, so x=1 and y=2
Entity ent4 = Entity(); //Default constructor, so x=0 and y=0
Entity ent5 = Entity(2, 3); //Made constructor, so x=2 and y=3
ヒープメモリ上にオブジェクトを作ることが可能であることは知っていますが、今私が求めているのはそれではないのです。
質問ですが、これらのオブジェクトの初期化方法の違いは何ですか?
いつ、どちらを使うべきか迷っています。
どのように解決するのですか?
Entity ent1;
上記のステートメントは、クラスのデフォルトコンストラクタを使用しています。
Entity
.
Entity ent2();
上記の宣言は、もし可能であれば、コンパイラによって関数のプロトタイプとして扱われるでしょう。これは、以下のようなケースとして知られている。 最も厄介なパース (MVP)であり、その存在が「括弧は使わない」という誤解を招く「賢い馬鹿ルール」の出現につながったのです。
このようなステートメントでは、ユーザー定義のコンストラクタが呼び出されます。
ent3
:
Entity ent3(1, 2);
また、MVPが打てるケースはこんな感じです。
Entity ent3_1(int(a), int(b)); // It's not what it looks like.
ent3_1
は変数ではありません。この文は、2つのint型パラメータを持つ関数を宣言しています。
int(a)
と同じです。
int a
は、C言語とその宣言文の遺産である。
Entity ent4 = Entity();
ent4
は
適切な
のバージョンです。
ent2
C++11までは、デフォルトコンストラクタは値の初期化の一部として呼び出されます。この形式により、曖昧さ解消の原則のために
ent2
と
ent3_1
が正しくありません。等号は代入ではありません。
operator=
の呼び出しがここで発生します。これは、初期化式をマークアップするための宣言構文の一部です。
Entity ent5 = Entity(2, 3);
ent5
は、ent3 caseのバージョンです。値の初期化の一部として、ユーザー定義のコンストラクタが呼び出されます。
あなたの質問にはC++11というタグが付けられており、C++11では統一された初期化構文が認められています。
Entity ent12{}; // This is a legal alternative of ent2 case
Entity ent13{1, 2}; // A call to constructor or member initialization
Entity ent13{ int(a), int(b) }; // Not a function anymore
Entity ent14 = {}; // Not an assignment
Entity ent15 = Entity{2, 3}; // Not an assignment either!
一様な初期化構文には注意点があることに注意してください。例えば、この行
std::vector<int> v(10);
は10個の要素からなるベクトルを宣言しています。しかし、この
std::vector<int> v{10};
は、値10を持つint型の単一要素で初期化されたベクトルを宣言しています。このようなことが起こるのは
std::vector
には、次のようなシグネチャを持つコンストラクタが定義されています。
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
MVPを発生させない()も、望ましくないコンストラクタを呼び出さない{}も使えない場合、値の初期化代入構文で問題を解決できます。
追記:必見 CppCon2018の様子。ニコライ・ヨスッティ "The Nightmare of Initialization in C++"
関連
-
[解決済み] Java で、あるコンストラクタを別のコンストラクタから呼び出すにはどうすればよいですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み] Pythonにはクラス内に「プライベート」変数がある?
-
[解決済み] コンストラクタのシグネチャを定義するインターフェース?
-
[解決済み] C++のstructとclassの違いは何ですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
-
[解決済み】Javaの「ダブルブレース初期化」の効率化?
最新
-
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++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む