定数ローカル変数を静的(c ++)として定義するメリットはありますか?


9
void Animation::playAnimation() const
{
    static const int index = 0;
    const std::string& animationFileName = 
    m_animationContainer.getAnimationName(index);
    static const int zOrder = -1;
    static bool isLooping = false;

    AnimationBank::play(animationFileName,
                        zOrder,
                        isLooping);
}

定数ローカル変数を次のように定義するメリットはありますstaticか?またはそれは不必要であり、悪い習慣ですらあります。



2
...も、しないでくださいクロスポストstackoverflow.com/questions/44431574/...「それは断片化された答えにつながるようクロスポストが眉をひそめているすべてのネットワーク上で飛び散った...」
ブヨ

質問を編集しました。
TM

回答:


10

@Christopheの非常に良い答えを超えて、staticに対して生成されたコードはローカル変数のコードよりも悪い可能性が高いので、内部の利点に興味がある場合、staticsは最新のプロセッサではより悪いです。

その理由は、他のすべてのスレッドや他のすべての呼び出しによって見つけられるメモリ内のどこかに静的変数を配置する必要があるためです。これは基本的にそれらをグローバルメモリに置くことを意味します。

長年にわたり、プロセッサーとコンパイラーは、グローバル、静的、フィールドなどの他の変数と比較して、使用頻度が高いため、ローカル変数へのアクセスを大幅に最適化しています。コンパイラーは、CPUレジスターにローカル変数を格納することを選択する場合があります。ローカル変数を格納しない場合でも(代わりに呼び出しスタックを使用します)、スタックのすべてがほぼ確実にキャッシュに格納されます。スタックへのアクセスは、通常、(スタックポインタレジスタから離れた)短距離アドレッシングモードです。ただし、グローバルまたはスタティックにアクセスするには、通常、拡張オフセットまたは絶対アドレスが必要であるため、結果として得られる命令は、スタックメモリアクセスの場合よりも長くなります。

そうは言っても、staticとconstの組み合わせにより、コンパイラーは使用時に定数値を置き換えることができることを検出する可能性があるため、おそらくconstを使用すると上記の問題が軽減されます。それでも、スニペットは少なくとも1つの非const静的を示しているので、おそらくトピックはトピックです。


6
静的定数をメモリに配置する必要がありますか?
MikeMB 2017年

5

これはメリットの問題ではなく、セマンティクスの問題です。

  • 関数内の静的変数(メンバー関数を含む)は、変数がその関数のすべての呼び出し間で共有されることを意味します。そのため、その関数の1つの呼び出しは、後続の呼び出しに副作用があります。

  • 非静的変数は、関数の実行ごとに一意です。

そのため、特定の正当な理由で必要とされない限り、ローカル変数を静的にしないでください。

追加の注釈: static変数は、異なるスレッド間でも共有されます。したがって、一度に複数のスレッドからこの関数を呼び出すと、競合状態とUBが発生する可能性があります(異なるオブジェクトに対して呼び出された場合でも)。


4
C ++ 11以降、標準ではスレッドセーフなconst静的変数が定義されています。一方、非定数の静的変数はそうではありません。
Teimpz 2017年

5
これは定数についてです。それらは値を変更できないため、複数の関数呼び出しとローカル関数呼び出しの間で共有される定数間に意味のある意味上の違いはありません。
MikeMB 2017年

唯一の違いは、初期化に副作用があるかどうかです。
MikeMB 2017年

1
@MikeMB確かに、私の答えは一般的でした。それがであるconst場合、オプティマイザは、そうであるかどうかにstaticかかわらず、とにかくそれを伝播します。しかし、まだ微妙な違いがあります。指摘したように、オブジェクト初期化子はいくつかの副次効果を使用する可能性があるため、静的または非選択を選択すると予想される動作を歪める可能性があります。これらすべての理由から、それがクラスに本質的にリンクされているものであるstatic場合にのみ使用することを強くお勧めしますconst。コードに意図を示し、オプティマイザにその仕事をさせます。
クリストフ

したがって、意味的には、変数が定数であり、そのアドレスが取得されない場合、違いはありません。残りの質問は次のとおりです。どちらを使用する必要がありますか?
user253751

1

ローカル変数は、関数が呼び出されるたびに初期化または構築されます。ローカル変数はスタックに格納されるため、通常はスレッドセーフです。

静的ローカル変数は、一度だけ初期化または構築されます。関数が初めて呼び出されたとき。ローカル静的変数はスタックに格納されないため、通常はスレッドセーフではありません。

constローカル変数は変更されない変数であり、関数が呼び出されるたびに初期化または構築されます。ローカルconst変数はスタックに格納されるため、通常はスレッドセーフです。

静的constローカル変数は変更されない変数であり、初期化または構築は1回だけです。関数が初めて呼び出されたとき。ローカル静的const変数はスタックに格納されないため、通常はスレッドセーフではありません。

コンパイラーは、const変数をコンパイル時定数に最適化できる場合があります。

コンパイラーは、スタックではなくレジスターにそれらを保持することにより、非静的変数を最適化できる場合があります。


なぜローカルstatic const変数はスレッドセーフではないのですか?それらの値がhepにある場合でも、それらの値は一定です。
統一モデリングサンドイッチ

@unifiedmodelingsandwich:2つのスレッドが関数の最初の呼び出しを同時に行うとどうなりますか?次に、両方のスレッドがそのstatic const変数を初期化しようとします。
Bart van Ingen Schenau 2017年

C ++ 11ではそうではありません。関数ローカル静的の動的初期化はスレッドセーフです。
Sebastian Redl 2017年

@BartvanIngenSchenau C ++ 11以降、静的ローカル変数の初期化はスレッドセーフです。Aは、一般にスレッドセーフではないと言ってもまだ正しいですが、これはC ++ 11より前の場合にのみ当てはまると言った方が正確です。
統一モデリングサンドイッチ

1
@unifiedmodelingsandwich:情報をありがとう。私は主にC ++ 03で行き詰まっています:-(
Bart van Ingen Schenau
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.