2012-06-24 19 views
26

OK、メンバ変数can be used初期化リストの他のメンバ変数を初期化する(初期化の順序などに注意して)。メンバー機能はどうですか?具体的には、このスニペットはC++標準に準拠していますか?メンバー関数を使用して初期化リストのメンバー変数を初期化できますか?

struct foo{ 
    foo(const size_t N) : N_(N), arr_(fill_arr(N)) { 
    //arr_ = fill_arr(N); // or should I fall back to this one? 
    } 

    std::vector<double> fill_arr(const size_t N){ 
    std::vector<double> arr(N); 
    // fill in the vector somehow 
    return arr; 
    } 

    size_t N_; 
    std::vector<double> arr_; 
    // other stuff 
}; 
+0

質問は良いですが、コードサンプルはやや人工的です。 'static_'として' fill_arr'を宣言するのを妨げ、その正当性を疑う余地はありません。 –

+0

これはスレッドセーフなのでしょうか?つまり、 'fill_arr'にローカルなベクトルがあります。' static'の場合は、それをある種のmutexで保護していますか? –

+2

'std :: vector arr'は_automatic storage_を持っていますので、' fill_arr'関数を呼び出すたびにそのインスタンスが存在します。それは基本的なものです.C++ _... –

答えて

30

はい、初期化リストのメンバ関数の使用は有効で、標準に準拠しています。

データメンバーは、宣言の順番で初期化されます(これは、宣言の順番に初期化リストに表示される理由です)。 N_が最初に初期化され、このデータメンバーをfill_arrに渡すことができました。 fill_arrはコンストラクタの前に呼び出されますが、この関数は初期化されていないデータメンバーにアクセスしないため(データメンバーにはまったくアクセスしません)、その呼び出しは安全とみなされます。ここで

C++標準の最新ドラフト(N3242 = 11から0012)からいくつかの関連exceptsである:

は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 
    } 
}; 
3

初期化リスト内のオブジェクトの初期化中に、オブジェクトはまだ完全に構築されていません。
これらの関数がまだ構築されていないオブジェクトの部分にアクセスしようとすると、それは未定義の動作です。
this answerを参照してください。

+0

それはまさに質問の要点です。メンバー関数の構築命令のルールは何ですか? –

+0

@Zhenyaこれを参照してください:: http://stackoverflow.com/a/3899583/981787 – Eight

+0

私が間違っている場合は私を訂正してください:メンバー関数ではなくメンバ変数を扱うと言われる質問です。メンバー関数が同じ規則に従うことを暗示していますか?一つは、gcc 4.4.3は 'arr_'と' fill_arr() 'の宣言の順序を入れ替えても、init-listの順序が宣言の順序と同じではないと警告を出しますが、 。 –

関連する問題