一般的に、メンバー静的関数のローカル変数はどこに格納されているのですか?
に依存します。静的定数の普通の古いデータ型は、読み取り専用のデータセグメントに格納されます。定数初期化子を有する静的変数をデータセグメントに格納し、動的初期化を必要とする静的変数をBSSセグメントに格納することができる。
静的関数内で静的変数が使用される場合、静的関数内で変数は1回のみ初期化されますか?
はい。この場合、SomeMapは最初のコントロールが宣言を通過するときに初期化されます。
静的ストレージ期間(3.7.1)を持つすべてのローカルオブジェクトのゼロ初期化(8.5)は、 の他の初期化が行われる前に実行されます。 定数式で初期化された静的記憶期間を持つPODタイプ(3.9)のローカルオブジェクトは、ブロックが最初に入力される前に初期化されます。実装では、 実装が名前空間スコープ (3.6.2)の静的ストレージ期間を持つオブジェクトを静的に初期化することが許可されているのと同じ条件下で、静的記憶期間を持つ他のローカルオブジェクトの初期化を実行することが許可されます。さもなければ、そのようなオブジェクトは、最初のコントロールがその宣言を通過するときに初期化されます。そのような オブジェクトは、初期化の完了時に初期化されたとみなされます。 を例外をスローすることによって初期化が終了すると、初期化は完了していないため、次回コントロールが 宣言を入力したときに再試行されます。
セクション6.7、ISO/IECのパラグラフ4 14882:上記のコードから2003(E)(申し訳ありませんが、私は標準便利の最新のコピーを持っていない)
?それは一度だけ初期化され、それがある場合にのみ初期化されます - 、などの静的宣言SomeMapの利点がある(私はそれが一度だけ初期化されることを期待する)
はい、それは静的な宣言に利点があります中古。 Test :: GetSomeMapが呼び出されない場合、SomeMapは決して初期化されません。
しかし、上記の@Blacktempelのように、Test :: GetSomeMapは余分なコピーSomeMapの作成に関する疑念を取り除くために、参照によって戻ってくるはずです。
また、3つの文字列(CONST1、CONST2、およびCONST3)を作成するコストが発生していることに注意してください。各文字列は、定数式文字列初期化子のコピーを格納するためにヒープメモリを割り当てます"const1"、 "const2"、 "const3")。さらに、Test :: GetSomeMapを呼び出すと、文字列のコピーを格納するためにヒープメモリを割り当てる可能性のあるSomeMapベクタを初期化するコストもかかります。あなたは、メモリ使用量と初期化のオーバーヘッドを懸念しているとあなたが本当に文字列の静的定数配列をしたい場合は
、ちょうどそうのように、1を宣言:
static const char* const * GetSomeMap(void) {
static const char* const SomeMap[] = {"const1", "const2", "const3"};
return SomeMap;
}
SomeMapはありません初期化のオーバーヘッドとメモリの最小値を消費します(そして全く変わることはない)。
一度初期化されますが、参照の代わりにマップのコピーが返されることに注意してください。それを修正したいかもしれません。 – Blacktempel
RVO(Return Value Optimization)は実行されないと想定できますか? – BubbleBoy
時にはクラスライターは、静的メンバ変数を静的メンバ関数内の静的ローカル変数に置き換えることによって回避します(しかし、関数は、あなたの例とは異なり、参照またはポインタを返す必要があります)。これは、複数の翻訳単位にわたる初期化を伴う問題を回避するため、または(ヘッダのみのクラス定義のために)実装ファイル内で静的メンバを初期化する必要性を回避するために行われる。 –