2

実際には同じものへの参照である場合とそうでない場合がある2つの参照を取る親クラスがあります。この場合、それらが同じ場合、Child クラスの初期化子リストでシーケンス ポイントの警告が表示されます。

class A
{
  public:
    A(int) {}
  private:
    A() {}
};

class Parent
{
  public:
    Parent(A&, A&) {}
};

class Child : public Parent
{
  public:
    Child() :
      Parent(
          *(_A = new A(0)),
          *(_A)) //Warning on this line
  {
  }

  private:
    A *_A;
};

int main(int argc, char** argv)
{
  return 0;
}

メモリが割り当てられた後にその行の逆参照が発生することが保証されていないためだと思います。いずれにせよ、私の質問は、親または A のいずれかに変更を加えずに、とにかくこれに関連するものはありますか?

4

1 に答える 1

4

そうです、親コンストラクターへの 2 つの引数が呼び出される順序は保証されていません (それらの間にシーケンス ポイントはありません*(_A)) *(_A = new A(0))

を動的に割り当てる必要がありますAか? そうでない場合は、次のことができます。

class Child : public Parent
{
  public:
    Child() : Parent( _a, _a ), _a(0) {}
  private:
    A _a;               // _A is reserved for the implementation (compiler + library)
};

1 つの注意点として、メンバーのアドレスを取得したり参照を取得したりすることは有効ですが、メンバーが初期化される前にその参照またはポインターを使用することは未定義の動作であり、コンストラクターが完了した_a後にのみ発生します。Parentつまり、Parentのコンストラクターが参照のみを格納し、オブジェクトを使用しない限り、安全です (ブレードの端に沿って乗っていますが、出血はありません)。

Parentコンストラクターが参照を保存以外の目的で使用する場合は、クラスを変更して、既に構築されたオブジェクトChildへのポインターを受け取ることができます。A

Child::Child( A* a ) : Parent( *a, *a ), _a(a) {}
于 2012-04-24T22:47:37.703 に答える