2017-12-04 13 views
0

別の場所で定義されており、呼び出されたときに、私は、乱数生成に関連する次のコードを含むマルチファイルのプログラムを書くためにしようとしている:help.hファイルで奇妙なRNG行動

:マサチューセッツ州

#include "help.h" 
random_device rand_dev; 
ranlux48 rand_eng{ rand_dev() }; 
uniform_real_distribution<> zero2one_dist(0, 1); 

:help.cppファイル内

extern random_device rand_dev; 
extern ranlux48 rand_eng; 
extern uniform_real_distribution<> zero2one_dist; 

in.cppファイル

#include "help.h" 
//identical as help.cpp, just for illustration of the problem 
random_device rand_dev1; 
ranlux48 rand_eng1{ rand_dev1() }; 
uniform_real_distribution<> zero2one_dist1(0, 1); 
//random number generation 
float rnd1 = zero2one_dist1(rand_eng1); 
float rnd2 = zero2one_dist(rand_eng); 
//main function 
int main() 
{ 
    //another random number generation. 
    float rnd3 = zero2one_dist(rand_eng); 
    //output 
    cout << rnd1 << endl << rnd2 << endl << rnd3 << endl; 
    return 0; 
} 

所望の結果は、0と1との間に3個の乱数を出力しているが、rnd1rnd3適切な結果を生成するが、rnd2は0を維持します!

が、私はここに完全に混乱している、外部ファイルの定義の違いは何でしょうhelp.hmain.cppにで、コールとの違いは、内側とメインの外に何が()?

私の実際の仕事では、コードをrnd2という形で書く必要がありますが、今はうまくいかず、理由がわかりません。

rnd1,rnd2rnd3の違いを誰にも示してもらえますか?rnd2を利用できますか?ありがとう!

+0

翻訳ユニット間の初期化順序の保証はありません。 'rnd2'は' zero2one_dist'の前後に初期化されます。実際に外部配布オブジェクトやヘルパー関数が必要な場合は、フォーム 'rnd3'を使用してください。 – spectras

+0

@spectras ** help.cpp **ファイルにヘルプ関数を書いています: 'float rand_zero2one(){return zero2one_dist(rand_eng); } 'しかし、この関数を' rnd2 = rand_zero2one() 'のように呼び出すことはできません... – Wjx

+0

@Wjx' rnd2'は一つの翻訳単位で静的なのでhelp.cppが偶数になる前に初期化されるかもしれませんそのコンストラクタを実行した。 –

答えて

3

翻訳単位間の初期化順序の保証はありません。 rnd2は、zero2one_distの前または後に初期化することができます。あなたが本当に外部配信対象、またはヘルパー機能が必要な場合は、たとえば、フォームrnd3を使用します。

float rand_zero2one() 
{ 
    static random_device rand_dev; 
    static ranlux48 rand_eng{ rand_dev() }; 
    static uniform_real_distribution<> zero2one_dist(0, 1); 
    return zero2one_dist(rand_eng); 
} 

これは、関数が最初に呼び出される前に、静的変数が初期化されている保証します。 helpファイルに入れ、extern変数の代わりに利用できるようにします。

さらに、あなたの意図がシングルトンになるようにする場合は、そうしてください。それらをsingleton classに入れ、次にMySingletonGenerator::instance().nextValue()を使用してください。

+0

ありがとう〜しかし、ここではもう少し質問があります:私は、複数の関数で同じ 'rand_dev'と' rand_eng'を呼び出せるようにしたいですか? – Wjx

+0

うわー、ありがとう!私はシングルトンについて何かを読んだことがあり、それは非常に有用であることが判明しました!(私はあなたが見ることができるようにC++の初心者です...)あなたの助けをたくさんありがとう! 〜 – Wjx

+0

@Wjxはい、2番目のコメントは実際に最初のコメントに答えます。ジェネレータをシングルトンクラスにすることで、複数の場所から使用できます。そうすれば、必要な方法を自由に設定できます。 – spectras