swapあれこれ
変数の中身を入れ替える。C++だと関数の参照渡しの例としてよく扱われますね。
void Swap( int& a, int& b ){
const int t = a;
a = b;
b = t;
}
どうせやるなら全ての型をサポートしたり
template< typename T >
void Swap( T& a, T& b ){
const T t = a;
a = b;
b = t;
}
まあ、テンプレートは冗談として(^^;
この方法は一時オブジェクトを生成する必要がある。一時オブジェクトなしに出来ないか?と言われれば実はできるんですよね。以前どこかで見たときは非常に感動しました。
void Swap( int& a, int& b ){
a = a - b;
b = a + b;
a = b - a;
}
これは、同じのを引いて足したら元に戻ることを利用して片方の変数に差分情報を埋め込んでいるんですね。ん?差分情報?ということは以前やったようにXORで代用できるんじゃないかな?かな? というわけで試したらうまくいきました。
void Swap( int& a, int& b ){
a ^= b;
b ^= a;
a ^= b;
}
引き算や足し算に比べたらXORの方が断然速いだろうからこっちのほうが速いんじゃないかなと思ってベンチとってみたら・・・殆ど変わりませんでした(^^; ただし、最適化コンパイルの場合はXOR版の方が倍くらい早かったり。どうやら最適化がかかりやすいっぽい。
ちなみにこの二つ、関数内で型を使っていないのでマクロに落とせます。
#define SWAP_INT(a,b){a^=b;b^=a;a^=b;}
#define SWAP(a,b){a-=b;b+=a;a=b-a;}
これで型は問いません。ただし、上はXORが定義されている必要があるので整数に限定ですけど。
ちなみにギャグでこんなもん作ってみました。
void Swap( int& a, int& b ){
_asm{
mov eax, a
mov ebx, b
mov a, ebx
mov b, eax
}
}
最適化ナシだと流石に速いです。ただし最適化したらXORに負けました(^^;
さらに調子こいて新しく覚えたことを無理に使ってみました。
void Swap( int& a, int& b ){
_asm{
push a
push b
pop a
pop b
}
}
メチャ重いですorz