その他もろもろ

傾向とか。



'03/07/16
ループ処理と剰余のコスト

たとえば、何かが回転して一周した場合、360度を越えたら0度に戻したいときがあります。
そういう場合、最初に思いついたのは

if(a>=360)
    a -= 360;

こんな感じでした。
しかし、剰余をつかえばもっと簡単に

a = a%360;

さらに省略して

a %= 360;

とシンプルに書けます。
これは他にも背景がループしながらスクロールする時や変数がある数値を越えると0に戻るときの処理にも使えます。
が、しかし剰余はちょっとだけコストがかかるらしくゲームループの中で毎回計算してるとちょっと重かったりします。(今時のCPUじゃ大した差は無いけど)
つまり、最初に書いた条件分岐のコードの方が速いんですが、この書き方にも弱点があって一気に360度以上の角度の変化があった場合対応できません。
だったら両方あわせちゃえってことで

if (a>=360)
    a %= 360;

これが速くて確実な書き方だと思います。とはいえボトルネックにならない限り私は剰余だけで済ませちゃいますが。
ちなみに%演算子が使えるのは整数の場合だけなので浮動小数点の場合はfmod()を使います。(C標準関数のfmodよりもC++テンプレート版のstd::fmodの方が型に囚われないので好きです)

if (a>=2π)
    a = std::fmod(a, 2π);

こんな感じ。

 

'03/07/16
スマポ戦国時代?

スマートポインタ系でも参照カウンタ付きポインタは割と重要なものだと思うのだが、当時C++の標準化作業は大幅に遅れていたせいか現在C++には標準搭載されていない。(まあauto_ptrでゴタゴタしてたぐらいだし)
おかげで、各ライブラリから色々な参照系ポインタが氾濫してしまって大変なことになってたりする。また腕に自信がある人は自作したりもするだろう。目的が同じなので基本的な動作はどれも似てたりするが、我々一般庶民がどのスマポを使うのかを選択するのは難しい。
とりあえず今の所boostのshared_ptr()がもっとも標準かなーと思うが……。

参考 http://www.kmonos.net/alang/boost/classes/shared_ptr.html

'03/??/??
環境依存の話だけどBoost Version 1.30.0 とVisual C++ .NET2003(VC7.1)にて

boost::formatを使用するとコンパイルエラーがでる。
これを解消するにはboost/format/feed_args.hppの73行目を下記のように書き換える

//#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1300)) コメントアウト
#if BOOST_MSVC <= 1300 && BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))

これでコンパイルが通るようになる。

(1.30.1で修正)






'03/06/23
ifの条件式の中での宣言

ANSI Cでは
「if文の条件式の中で宣言された変数のスコープはそのif文のブロックのスコープになる」
らしい。

つまり
for(int i=0; i<10; i++){....}
のように書けば変数iをこのfor文でのカウンタ専用という意味にできる。プログラムのブロック構造的にも判りやすい。

だが、VisualC++6.0以前は何故かこのルールではなかった。

for(int i=0; i<10; i++){....}
for(int i=0; i<20; i++){....}

なんてコードを書くとiが2回宣言されてますというエラーが出てしまっていた。

というわけで以前はiを関数のはじめの方で宣言して使いまわしたり、変数をユニークな名前していたのだが。
VC7になってからはちゃんとANSIに準拠するようになった。それ以来サルのように条件式内変数宣言を使いまくっている。

特にSTLを使いまくっていると嬉しいのがイテレータを使う処理を

for(list<CSprite>::iterator it=enemy.begin(); it!=enemy.end(); ++it) {
    it->Draw();
}

for(list<CObject>::iterator it=obj.begin(); it!=obj.end(); ++it) {
    it->Release();
}

とスマートに書けることだ。
以前はイテレーターが出てくる度にit2,it3なんて嫌な名前付けてたのであった。
同じ関数内に何度もイテレーターがでてくるような長いコードを書くなという戒めかもしれないが……。



'03/06/23
#pragma onceの使用

ヘッダファイルの重複インクルードを防ぐには

#ifndef __HOGE_H__
#define __HOGE_H__
(内容)
#endif // __HOGE_H__

と、おまじないを書く。ここまでは単なる常識かもしれないが、
実はヘッダの先頭に #pragma once と書くだけでも上記と同じ意味になる。#pragma onceはヘッダファイルの重複を防ぐディレクティブだ。しかも一行で済むのでコードもスッキリして気分が良い。

だが#pragmaと言うだけあってANSI標準ではない。以前ならそんなコンパイラ依存っぽい機能など使わないのが普通であるが。
最近では状況が違ってるようで割と#pragma onceを使ったコードも見かけるようになった気がする。
調べてみると現在主要なコンパイラ(VC、BC,gcc、CodeWarrior)では普通に#pragma onceが使用できるらしい。

というわけで私も#pragma onceの恩恵に与ることにしました。
#define使っている人もどうですか(普及活動?)


戻る