6

MarshallP.ClineによるC++FAQ(2nd Edition)(ペーパーバック)のセクション16.4、Greg Lomowは、静的データメンバーが初期化される前に関数が呼び出される可能性があるため、インライン関数は静的データメンバーに安全にアクセスできないと述べています。

これがインライン関数に適用され、別の変換ユニットの静的データメンバーを呼び出す他の変換ユニットの関数だけに適用されない理由がわかりません。この災害で「インライン」がどのような役割を果たしているのかわかりませんか?

4

1 に答える 1

6

static変数は、同じ変換ユニット(多かれ少なかれcppファイル)内の関数が実行される前に完全に初期化されます。が別の変換単位にある main場合、が呼び出される前に初期化されることは保証されません。関数は複製され、各変換ユニットには独自のコピーがあります。つまり、変数とは異なる変換単位のインライン関数は、変数が適切に初期化される前にその変数に対して読み取り/書き込みを試み、未定義の動作を引き起こす可能性があります。(ルールは非常に複雑ですが、それは私が覚えていることです)maininlinestatic

§3.6.2/4静的ストレージ期間を持つ非ローカル変数の動的初期化がmainの最初のステートメントの前に行われるかどうかは実装によって定義されます。mainの最初のステートメントの後のある時点まで初期化が延期される場合、初期化される変数と同じ変換単位で定義された関数または変数の最初のodr-use(3.2)の前に発生するものとします。

§3.2/3インライン関数は、それがodrで使用されるすべての変換単位で定義されるものとします。

私の知る限り、インライン関数は非インライン関数ほど危険ではありません。別のTUの静的関数にアクセスする関数は危険であり、inlineたまたますべてのTUに関数を配置するため、それらのほとんどは安全ではありません。回避策の1つは、「最初に使用するイディオムで構成する」を使用することです。

暗黙的なテンプレートの特殊化は複雑ですが、完全を期すために:

§14.7.1/3[temp.inst]静的データメンバーの初期化(および関連する副作用)は、静的データメンバー自体が静的データメンバーの定義を必要とする方法で使用されない限り発生しません。存在。

したがって、テンプレートクラスの静的メンバーは、使用前に常に初期化されます。

上記のすべては、前述の 「最初の使用で構築するidom」が解決する静的初期化順序fiasco)の対象となります。

于 2013-03-05T21:39:46.277 に答える