5

Parashiftは初期化リストについて詳しく説明していますが、ctor本体で割り当てる前に変数の追加コピーが作成される理由については説明していませんが、初期化リストを介して割り当てた場合、追加コピーは作成されません。
前者は代入前の一時的なiの作成を回避するため、i++の代わりに++iを使用するというアドバイスにも出くわしました。コンストラクター本体に割り当てられたPODについても同じですか?割り当てが行われる前に一時変数が作成されますか?

別の言い方をすれば、コンパイラが変数の追加コピーを作成する必要があるのはなぜですか?変数を直接割り当てることができないのはなぜですか?
なんで?

4

3 に答える 3

3

次のことを考慮してください。

struct C { 
    C() { /* construct the object */ }
};

struct X {
    C member;

    X() { member = C(); }
};

コンストラクターは、次のX()ように言った場合と同じです。

X() : member() { member = C(); }

まず、Cコンストラクターを呼び出してmemberデータメンバーを作成します。次に、の本体Xが実行され、2番目の一時Cオブジェクトが作成されてに割り当てられ、一時オブジェクトmemberが破棄されます。


これは、自動的に初期化されるタイプの場合のみであることに注意してください。memberが型intまたはPODクラス型(例として)の場合、コンストラクターの本体が入力されたときに初期化されませんX

このようなタイプの場合、初期化リストでデータメンバーを初期化するか、コンストラクターの本体でデータメンバーに割り当てるかは、パフォーマンスの観点からは実際には重要ではありません。違いは完全に文体です。可能であれば、一貫性を保つために初期化リストを優先する必要があります。

于 2011-07-13T05:32:51.307 に答える
2

特にコピーに関する最初の質問に対処するには(「++i」と「i++」に触れずに):

コンストラクターは関数であり、パラメーターがあります。これらのパラメーターは、パラメーターとして渡される変数のコピーです(参照による受け渡しが使用されている場合を除く)。これで、このコピーを操作したり、他のことを実行したりできます。次に、割り当てるときに、このパラメーターのコピー(操作される可能性)を取得して、メンバー変数に割り当てます。初期化リストを使用すると、コンパイラーはこのコピーがなくてもすぐに割り当てを最適化できます。これは、初期化以外には使用しないためです(メンバー変数に割り当てる前に変更することはできません)。

于 2011-07-13T05:36:26.277 に答える
2

ctor本体での割り当ての前に変数の追加コピーが作成されるのに、初期化リストを介して割り当てられたときに追加コピーが作成されないのはなぜですか。

割り当ては初期化に続くためです。つまり、割り当てはオプションですが、初期化は必須です。PODの違いにあまり気付かないかもしれません。ただし、ユーザー定義のデータ型についても同じことが言えます。

i++の代わりに++iを使用することのアドバイス

繰り返しますが、PODの場合はそれほど重要ではありません。ただし、ユーザー定義クラスの場合i++、一時的なコピーを作成します。したがって、を使用することをお勧めします++i

struct A {
  A operator ++ (int)  // example of i++
  {
    A temp = *this;
    this->value ++;
    return temp;    // makes 2 copies "temp" and return value
  }
  A& operator ++ ()  // example of ++i
  {
    this->value ++;
    return *this;  // no copy
  }
};
于 2011-07-13T05:41:49.050 に答える