5

次のコードを検討してください。

struct Calc
{
   Calc(const Arg1 & arg1, const Arg2 & arg2, /* */ const ArgN & argn) :
      arg1(arg1), arg2(arg2), /* */ argn(argn), 
      coef1(get_coef1()), coef2(get_coef2()) 
   {
   }

   int Calc1();
   int Calc2();
   int Calc3();

private:
  const Arg1 & arg1;
  const Arg2 & arg2;
  // ...
  const ArgN & argn;

  const int coef1; // I want to use const because 
  const int coef2; //      no modification is needed.

  int get_coef1() const {
     // calc coef1 using arg1, arg2, ..., argn;
     // undefined behavior?     
  }
  int get_coef2() const {
     // calc coef2 using arg1, arg2, ..., argn and coef1;
     // undefined behavior?
  }

};

struct Calcget_coef1電話をかけたときに完全に定義されていませんget_coef2 。このコードは有効ですか?UBを取得できますか?

4

3 に答える 3

8

12.6.2.8:作成中のオブジェクトに対してメンバー関数(仮想メンバー関数、10.3を含む)を呼び出すことができます。同様に、作成中のオブジェクトは、typeid演算子(5.2.8)またはdynamic_cast(5.2.7)のオペランドにすることができます。ただし、これらの操作が、基本クラスのすべてのmem-initializersが完了する前に、ctor-initializer(またはctor-initializerから直接または間接的に呼び出される関数)で実行された場合、操作の結果は未定義です。

したがって、この方法でクラスメンバーを初期化できますが、基本クラスを初期化することはできません。また、他の人が指摘しているように、関数がそれらの値の一部を使用する場合は、メンバーの初期化順序に注意する必要があります。

于 2010-03-22T13:10:15.100 に答える
3

計算が依存する変数は呼び出し時にすでに初期化されているため、未定義の動作であってはなりません。関連情報については、この質問を参照してください。

于 2010-03-22T13:00:22.250 に答える
0

未定義ではありませんが、これらのメンバー関数が初期化された値のみを使用していることを絶対に確認する必要があります。また、値は、初期化リストに表示される順序ではなく、クラスに表示される順序で 初期化されることにも注意してください。例えば:

struct Foo
{
  int a, b;
  int c;
  Foo(): c(1), a(1), b(1) {}
};

そのコンストラクターでは、変数はa、b、cの順に初期化され、リスト内の順序は何も意味しません。したがって、のa計算を使用しての値を初期化する場合は、の宣言をとの次のポイントに移動する必要がありbます。cabc

于 2010-03-22T13:06:25.147 に答える