• ベストアンサー

staticの動作について

C++で趣味でゲームを作っているのですが、staticを使ったときのローカル変数の動作について質問があります。 いまいち、ローカル変数の動作が分かっていないのですが、大雑把には、関数が読み出される毎に空いてるメモリを探して、そこを確保する物だと思ってます。 で、staticを用いて宣言すると内容が保持されると言うことは、これは始めに一回だけメモリの確保をして、以降はそれを継続して使っているというものなのでしょうか? だとすると、staticをつかったローカル変数の方が、繰り返しメモリの確保が行われ無い分、処理が早いということでしょうか? いま、ゲーム内では、描画用の関数描画基準座標とサイズを受け渡して入るのですが、どうしても内部で描画終了点と開始点のクリップを計算する必要があり、そのためにどうしても計算した開始点、終了点を保持する変数が必要になっています。 しかし、描画関数はキャラの分と背景描画の分とパーティクルの描画の分と、ゲーム1ループないでも1000回近く(多いときは2000回ぐらい)呼び出されてます。 その度にメモりの確保をされるのはなんか気分が悪いなぁと思ってstaticを何となくつているのですが、実際の所staticを着けたら動作がはやくなるとかと言うことは無いのでしょうか? 宜しくおねがします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Interest
  • ベストアンサー率31% (207/659)
回答No.2

メモリの構造について理解すると、static をつけるとどうなるか理解できると思います。 プログラムのメモリは大雑把に分けると次の4つの領域(セクション)から構成されます。 (a) 実行コード領域 (b) データ領域 (c) スタック領域 (d) ヒープ領域 (a)実行コード領域と(b)データ領域の中身は名前の通りで、一度メモリ上に確保されるとその場所はずっと変わりません。外部変数はデータ領域に確保されます。 (c) スタック領域はローカル変数や関数の引数、関数の呼び出し元へのリンクなどに使用されます。再帰関数を使用するとあっという間にスタックが消費されて溢れてしまい、スタックオーバーフローを起こすことがあります。 (d) ヒープ領域はC言語ならmalloc/calloc、C++ならnewを使ってメモリを確保する場合に使用される領域です。new して確保した領域を deleteしない処理を繰り返すと、使用可能なヒープ領域がだんだん減っていき、メモリリークが発生します。 さて、staticを使ったローカル変数ですがこれはスタック領域ではなくデータ領域に確保されます。というのは、staticなローカル変数をヒープ領域に確保してしまうと、その関数を抜けたらローカル変数に割り当てたメモリを返却しなければいけなくなり、値を保持できなくなるからです。 > staticを用いて宣言すると内容が保持されると言うことは、 > これは始めに一回だけメモリの確保をして、以降はそれを継続 > して使っているというものなのでしょうか? その通りです。データ領域に確保して、継続して使っています。 > だとすると、staticをつかったローカル変数の方が、 > 繰り返しメモリの確保が行われ無い分、処理が早い > ということでしょうか? いいえ、そのようなことはありません。パソコンの場合、CPUがプログラムを動かすために使用するメモリは高速な順に次のようになっています。 (1) CPU内部のレジスタ (2) CPU内部のキャッシュメモリ(1次キャッシュ、2次キャッシュ) (3) DDR-SDRAMなどの主記憶 CPUのコアはプログラムを実行するのに直接主記憶(ここではDDR-SDRAM)にアクセスすることができず、CPU内部のレジスタに命令やデータをロードしてから次に実行すべき処理を判断します。このCPU内部のレジスタは非常に高速(※1)ですが、レジスタの数は非常に少なく(※1)、多くの命令やデータを保持することができません。 ※1 CPUのコアと同じ速度で動作する。 ※2 PowerPCなど一般的な32bit RISC CPUでは32bit×32個程度、インテルのIA-64アーキテクチャ CPUの場合は 128個程度。 CPUコアに対して主記憶は非常に遅い(※3)ため、CPUと主記憶の間にキャッシュメモリを入れて、頻繁に使うものだけキャッシュに入れて速度差を補っています。 ※3 例えばCPUコアのクロックが3GHzに対して DDR2 SDRAMのクロックが800MHzなど。 以上を踏まえると、ローカル変数にstaticをつけてもつけなくても、CPU内部のレジスタから外に出てしまえば処理速度に差はありません。おそらく、コンパイラで最適化をかけると消えてしまう程度の差だと思います。

koutai
質問者

お礼

すいません返信が遅れてしまいました。 なるほど、コンパイラで最適化がかかれば消えてしまうほどのものなのであれば、staticはどうしても値を継続して使いたいときだけにした法が良いみたいですね。 すっきりしました。 ありがとうございました。

その他の回答 (1)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

実際のところ、ほとんど違いはないですし、むしろ遅くなる可能性もあります。 staticなしのローカル変数(auto変数といいます)は多くの実装でスタック上に取られます。このスタックに取るというのは非常に高速なのです。 したがって、メモリの確保に要する時間はほとんどゼロで済みます。 また、最近(でもないか)のCPUではメモリキャッシュという仕組みがあります。 この仕組みのため、近いところに格納されているメモリをアクセスする分には高速でも、別のところに格納されているメモリをアクセスする際に速度が低下する場合があります。staticをつけると別のメモリに格納されるため、かえって遅くなる可能性があります。といっても、ほんのわずかでしょうが。 こういった疑問が生じた場合は実際に速度を測定してみるといいですよ。

koutai
質問者

お礼

ご回答ありがとうございます。 むしろ遅くなってしまうこともあるのですか...。 なるほど、早速不必要なstaticをはずさなければなりませんね。(苦笑) 今度から自分でも速度を測定してみます。

関連するQ&A

  • C言語のStatic変数について

    現在、C言語の勉強しながらゲームプログラムにチャレンジしています。 二つの関数で利用する変数を作りたかったので、Static宣言された変数を容易しました。 ですが、この変数、一度処理が終わると当面使わない変数なのです。 (ただし、処理途中は何度も呼び出されるので値は保持しなければいけません) よって、メモリ上に延々居座られるのが邪魔に思えて仕方ありません。 実際、大したことないだろうとは思うのですが。 このStaticで宣言された変数を、自分の好きなタイミングでメモリ上から解放するような処理はできませんか? もしくはメモリ上に居座ることのない処理の仕方などありましたら、 考え方を教えていただけるとうれしいです。よろしくお願いします。

  • 関数内、ファイルのstatic変数

    関数内で、static変数を宣言した場合に、その値は保持されると 思いますが、その関数の外からポインタで見る場合にその値は 保証されるのでしょうか? (必ず同じメモリ上に配置されるのでしょうか?) また、関数とファイル内static変数においてスコープ以外に 取り扱いが変わったりするのでしょうか? (配置されるメモリ空間等) よろしくお願い致します。

  • static 変数について

    static 変数について 今、C++を勉強しているのですか、static変数がどのように動くのかよくわかりません。 下のプログラムのint a はローカル変数だから、ブロックを抜けたら、初期化されるためstatic変数にして、ブロックを抜けても値を保持するようにすってことはわかるのですが 毎回このブロックに入る度、static int a = 0;を読むことになり、その前に入っていた値はなくなるのではないでしょうか?それとも,static int a と書かれていると,1度しか実行されないから、値が保持され続けるのでしょうか? int add (int x ) { int a = 0; a += x; return a; }

  • 『関数内static変数』の別名って??

    1、『関数内static変数』の別名で一言の呼び方ってありますか?? 2、『static変数』と呼ぶときは通常、ファイル内で有効な変数(この場合だとファイルローカルな変数??)と考えてよいのですね? おねがいしますm(_ _)m

  • Static変数の必然性について

     今晩は、Cの初心者です、宜しくお願いします。    Global変数とStatic変数の違いがよく分かりせん。  本を読むと、Global変数は「常に同じメモリ上に置かれどの関数からも使用できる」、Static変数は「常に同じ メモリ上に置かれ定義された関数からのみ使用できる」とかいています。  Global変数がどのようなもので、その必要性みたいなものは理解出来るのですが、Static変数については、 Global変数との違い、その必要性、実際にどのような場合に使うのかその必然性みたいものがあるのか理解できません。  いくら本を読んでも、理解出来ないのですが、宜しくご教示願います。

  • staticのメモリ共有について

    staticについて調べたのですが、その内容があっているのかどうか 間違い・アドバイスなどありましたら是非伺いたいと思います。 よろしくお願い致します。 ------------------------------------------------------------  シェルから起動されるJavaでバッチ処理を行うアプリケーションを  作成していまして、サーバマシンの複数のプロセスから起動されます。  (つまりjavaコマンドが複数回同時に実行されます)  1回の実行の間保持しておきたい値をstaticなクラス変数に格納しています。  そしてそれは、1回の実行の間はずっと同じなのですが、  プロセスごとに異なる値です 。  この時、この1回の実行の間に保持しておきたい"static"な変数は  次のプロセスから実行された時に書き換えられるのか?  という疑問がでたのが始まりです。  マルチスレッドの処理はありません。 ------------------------------------------------------------ 調べたところ、 ■1台で2つ以上のJavaアプリケーションを実行する場合、  それぞれのアプリケーションを個別にjavaコマンドで起動・・・  =>javaコマンド毎に"個別のJVMが"それぞれのプロセス上で動作する。 ■フィールドをstatic指定するとクラス変数となり、  ロードされたクラスごとに"JVM上に"1つしか存在しない変数となる。 ・以上の2点から、staticの変数がメモリ上で共有されるのは  1つのJVM(1プロセス)内での話しであり、他のプロセスから  その値を書き換えられる事はないと考えています。  そして、1プロセス内でのマルチスレッドな処理を行っている場合、  staticな変数の値は注意が必要だけど、  複数プロセスでシングルスレッドな処理を行っている場合、  (性能などの問題上staticにするかどうか良し悪しはあるとしても)  staticな変数の値の不整合について  考慮は不要と考えても宜しいのでしょうか? 経験が浅い為、確信が持てずにいる状況です。 宜しくお願い致します。

    • ベストアンサー
    • Java
  • static宣言について

    現在、c言語とDXライブラリを使ってゲームを製作しています。 http://okwave.jp/qa/q8270456.html 前回、このような質問をさせていただき、原因らしき箇所を突き止める所までいきました。 と言いますのも、配列の要素を指定する箇所(分かり辛かったらすいません。要素数ではありません)に、static宣言された変数を入れるとなぜかプログラムが強制終了されてしまうのです。 加えて、DXライブラリのGetColor関数にも返ってきた色をStatic宣言された変数に格納すると、何故か指定された色と違う色が出てしまうことが分かりました。 なんとか、その関数が終わる度に値を格納したかったので、色々試しました。 直接Static宣言されていない変数を間に噛ませてみたり、同じcpp内にわざわざ別の関数を用意して、そちらでStatic宣言し、値を返してみたり、と色々とやったのですが上手くいきませんでした。 ****************************************** int hairetu[20]; Static int z = 0; int x = z-1+1 hairetu[x] = zahyouX; (static宣言された変数zでhairetu[]の[]内を指定しようとするとダメ) (上記のように意味のない計算をさせてstatic宣言されていない変数を間にかませてもダメ) ****************************************** 結局の所、別のcppを用意して、ただ一つのStatic変数を+1していくだけの関数をくみ上げた所、上手くいったのですが・・・。何故このような事が起きるのでしょうか。 Static宣言された変数の決まりごと、もしくは、このような状態になってしまった原因など、見当がつきましたら教えていただけると有難いです。よろしくお願いします。

  • static変数について

    struct XXX { char *aaa; char *bbb; }; static struct XXX YYY[] = { {NULL, "JJJ"}, ... }; thread(){ ... } 上記のstatic変数をスレッド関数thread()の外部変数として設定した場合、 *aaaの値はスレッドごとには確保することできませんでしょうか。 上書きされてしまうのでしょうか。 やはりスレッドセーフではないのでしょうか。 その際、どのように設定してあげればよいのでしょうか。 どなたかご教授お願いします。

  • 関数外からstatic変数を再度初期化できるのでしょうか?

    以下の静的変数?についてA,Bのメモリは別でしょうか? test関数外からBの変数を再度初期化できるのでしょうか? staticの仕組みがわからないのでstaticのメモリの初期化のタイミングとメモリアクセス方法について知りたいです。 static x = 1; // ---A int test() { static int x = 0; // --- B } またexternの働きも知りたいです。

  • マルチスレッド下でのインスタンス変数・クラス変数

    よろしくお願いします。  マルチスレッド下で動作するクラスを作成しています。データにアクセスするためのオブジェクトを クラスのフィールド値として保持し、使い回しを行いたいと考えています。このデータアクセスオブジェクト(以下Dao)内では特にフィールドは使用せず、全てローカル変数のみで動作するようになっています。Dao自体は初回のクラス生成時にstatic処理にてフィールドにセットされます。  このDaoを保持するフィールドは、staticなクラス変数が良いのか、インスタンス変数として保持する方が良いのか迷っております。  クラス変数ならばPermanent領域をオブジェクト1つ分のメモリ使用で済み、インスタンス変数だとスレッド毎にheapを使い、処理数が増えるとメモリ圧迫しちゃう?と安易に考えてしまったりしています。  ご意見・ご助言よろしくお願い致します。

    • ベストアンサー
    • Java

専門家に質問してみよう