2017-10-08 17 views
0

C++でオブジェクト(クラスまたは構造体のインスタンス)を初期化する方法はさまざまです。一部の構文ではオブジェクトの直接初期化が表示され、その他の構文ではコピー初期化が返されます。コンパイラでcopy-elisionが有効になっている場合、どちらも同じパフォーマンスを示します。 copy-elisionを無効にすると、後者(コピー初期化)を選択したときに、すべてのインスタンス化時に追加のコピー/移動コンストラクタ呼び出しがあります。ダイレクト初期化またはコピー初期化ですか?

結論:コピー初期化にはパフォーマンス上のペナルティがあります。次の質問から

C++11 member initializer list vs in-class initializer?私は、これはコピー初期化構文であろうと結論付けることができます:

obj s = obj("value"); 

そして、これが直接初期化になり構文:

obj s{"value"}; 

 
これはどうですか:

obj s = {"value"}; 

そして、この1:

obj s = obj{"value"}; 

そして、この1:

obj s("value"); 

またはこの1:

obj s = "value"; 

NOTE
ビャーネ・ストロヴストルップは、ページ311、§9.4.2に第2版、「C++を使用してプログラミング、原則と実践」彼の本の中でいくつかの初期のスタイル(すべてではない)を比較:

struct Date { 
    int y,m,d;      //year, month, day 
    Date(int y, int m, int d);  //check for valid date and initialize 
    void add_day(int n);   //increase the Date by n days 
}; 

を...

Date my_birthday;     //error: my_birthday not initialized 
Date today{12,24,2007};    //oops! run-time error 
Date last{2000,12,31};    //OK (colloquial style) 
Date next = {2014,2,14};   //also OK (slightly verbose) 
Date christmas = Date{1976,12,24}; //also OK (verbose style) 

氏Stroustrup氏は、同じように、これらの異なる初期のスタイルを提示します。少なくとも、それは私に見える方法です。それにもかかわらず、いくつかは直接初期化およびその他コピー初期化である可能性があります。これらの用語については、本の時点でまだ説明していないためです。


EDIT
与えられた答えは何か面白いものを持ち出します。
どうやら、これは直接初期化です:

obj s("value"); 

そして、これは直接リスト初期化です:あなたのいくつかが指摘するように、差がある

obj s{"value"}; 

。実際にどのように違うのですか?その違いは、最適化されていないコンパイラの出力で目立つでしょうか?一般に

+0

'='はありますか?はい:コピーの初期化です。そうでない場合は直接初期化です。 – Rakete1111

+0

@ Rakete1111 [それは本当ではないようです](http://coliru.stacked-crooked.com/a/18e4e0f6db8a9bfc)。 – nwp

+0

@nwpもちろん、中括弧を使用すると、 '='に応じて* -list-initializationになります。ごめんなさい、ありがとう! – Rakete1111

答えて

3
obj s = obj("value"); 

これは、変数sを初期化コピーするために使用されるprvalue、直接初期化です。 C++ 17のprvalueルールは、この事実を直接的にsの初期化にします。

obj s{"value"}; 

これはダイレクトリスト -initializationです。 「リスト」の部分は重要です。オブジェクトを初期化する目的でbraced-init-listを適用するたびに、リストの初期化が実行されます。

obj s = {"value"}; 

これは、コピーリストの初期化です。

obj s = obj{"value"}; 

これは、変数sを初期化コピーするために使用されるprvalue、直接リスト初期化です。直接初期化され

obj s("value"); 

。コピー初期設定だ

obj s = "value"; 

氏Stroustrup氏は、これらの異なる初期化スタイルを同等として提示しています。

これらは、ほとんど同じことをする意味では同じです。しかし、技術的には同等ではありません。コピーリストの初期化では、コンストラクタexplicitを呼び出すことはできません。したがって、選択されたコンストラクタがexplicitの場合、コードはコピーリスト初期化のケースでコンパイルに失敗します。

+1

技術的には、[直接初期化](https://wg21.link/dcl.init#16)にはダイレクトリスト初期化が含まれています。それで、L(E)WGは ''非リスト初期化 ''(http://eel.is/c++draft/defns.direct-non-list-init)オプションの "と友人。 –

+0

ありがとうございました。私の質問で** EDIT **を見てください。 ** direct-initialization **と** direct-list-initialization **の違いについてもっと知りたいです。 –

+0

@ K.Mulier: "list initialization"を参照してください。それが原則の違いです。 –

2

あり、右側は、暗黙的に変換されます。タイプTの一時インスタンス。そこから012その後がコピー/移動構築されます。

氏Stroustrup氏は、同じように、これらの異なる初期のスタイルを提示します。

多くの場合、生成された(最適化された)コードはまったく同じです。コンパイラは、副作用がある場合でも、コピーの構成をelideにすることができます。現代のコンパイラは、このような単純な最適化をはるかに超えているので、このエリジョンを効果的に評価することができます(これはC++で必須です)。

セマンティクスが異なるため、コピーと直接初期化の違いは非常に重要です。たとえば、explicitと宣言されたコンストラクタの呼び出しは、直接初期化でのみ可能です。


形態T s = {...};copy-list-initializationであり、いくつかの特殊なリストの初期化規則に従います。

+0

しかし、違いがあります。コピーリストの初期化には、一時的なものはありません。 – Rakete1111

+1

@ Rakete1111 - trueですが、* copy-list-initialization *と* direct-list-initializationの間にはまだ違いがあります(http://eel.is/c++draft/dcl.init#list-3.2) *。 – rustyx

+0

ありがとうございます@RustyX。私の質問でEDITを見てください。直接初期化とダイレクトリスト初期化の違いについて詳しく知りたいと思っています: –

2

簡単にlook upこれらの種類の質問に対する回答ができます。つまり、簡単な答えは、=はコピー初期化を意味します。ただし、T t={...};コピーリスト初期化です(中括弧にはTまたはそれに由来するもののみが含まれていない限り)コピーは含まれていません。ただし、非explicitコンストラクタの使用を許可しません。

関連する問題