はい、初期化リストでのメンバー関数の使用は有効であり、標準に準拠しています。
データメンバーは、宣言の順序で初期化されます(これが、宣言の順序で初期化リストに表示される理由です。この例で従ったルールです)。N_
は最初に初期化され、このデータメンバーをに渡すことができますfill_arr
。fill_arr
はコンストラクターの前に呼び出されますが、この関数は初期化されていないデータメンバーにアクセスしないため(データメンバーにはまったくアクセスしません)、その呼び出しは安全であると見なされます。
C ++標準の最新ドラフト(N3242 = 11-0012)からのいくつかの関連する例外を次に示します。
§12.6.2.13:メンバー関数(仮想メンバー関数、10.3を含む)は、構築中のオブジェクトに対して呼び出すことができます。(...)ただし、これらの操作がctor-initializer(または直接または間接的に呼び出される関数)で実行される場合ctor-initializerから)基本クラスのすべてのmem-initializersが完了する前に、操作の結果は未定義です。例:
class A { public: A(int); };
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined: calls member function
// but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined: calls member function
// but base C not yet initialized
i(f()) { } // well-defined: bases are all initialized
};
§12.7.1:重要なコンストラクターを持つオブジェクトの場合、コンストラクターが実行を開始する前にオブジェクトの非静的メンバーまたは基本クラスを参照すると、未定義の動作が発生します。例
struct W { int j; };
struct X : public virtual W { };
struct Y {
int *p;
X x;
Y() : p(&x.j) { // undefined, x is not yet constructed
}
};