2007年6月14日木曜日

ぐぉーなぜじゃーOrz

C#で組んだアルゴリズムが過去にC++で組んだモノより圧倒的に遅くて凹んだOrz ネイティブとCLRの差があるとはいえ多分実装の差が顕著に出てるんだろうなぁ・・・。
可読性は圧倒的にC#で組んだモノの方がいい(はず)なんだけど、これじゃちょいと実用に耐えられない。可読性重視で組んだとはいえ、ある程度は効率性も考慮して組んだつもりだったのでこの結果はショックでかいんだよなぁ。
と、いうわけで、C#で実装したアルゴリズムをC++へポーティングすることに。ついでにアクセス権はかなりゆるめにして、使用者に管理させることに路線変更。
どのみち外部へ公開するようなソースってわけでもないし、そこまでガチガチにこだわる必要はないだろうってな感じかな。
ところで、C++は組み込みの配列がポインタと区別されていないため、配列長をメンバとして持っていないなどちょいと不便。ってなわけでちょー簡易固定長スタッククラスを実装することに。[]演算子をオーバーロードしてやってもよかったけど、ポインタ(配列)をメンバとして保持して、それをパブリックで公開してしまった方が他のライブラリとかに適用させやすいと考えて公開しちゃうことに。
外部からdeleteされる可能性もあるけどそんなの知ったこっちゃない(ぁ そこはもう、ね、ほら、暗黙の了解ってコトで。
とまぁ実装してみたはいいけれど、なんと実行エラーがOrz しかも原因が分からないOrz
コンストラクタにてnewで配列を確保したからデストラクタでdelete[]を呼び出してるんだけど、deleteした瞬間例外発生。なんでやねんOrz ちなみにdeleteでも同じ結果でした。どゆこと!?
もう埒が明かないのでソースを公開してみる。誰か突っ込んでくれないだろうか・・・?

///


/// 簡易固定長スタッククラス
///

class Array
{
private:
int nSize;
public:
double* array;
///
/// 要素数を指定して初期化
///

/// 要素数
Array(int nSize)
{
array = new double[nSize];
memset(array, 0, sizeof(double) * nSize);
this->nSize = nSize;
}
///
/// 確保した領域を開放
///

///
/// バグを抱えている。なぜかdeleteすると例外発生。ちゃんとアドレスは持ってるのに・・・?
///
~Array(void)
{
delete[] array;
}
///
/// 配列の要素数を返す
///

/// 配列の要素数
int Length()
{
return nSize;
}
///
/// スタックに値を追加
///

///
/// 固定長スタック扱い。末尾の値は捨てられる
///
static void Push(Array& array, double value)
{
memmove(&(array.array[1]), array.array, sizeof(double) * array.Length() - 1);
array.array[0] = value;
}
};


む、コメントのCSSタグが一部消えちゃったな。まぁいいか。
memmoveがいかんのだろうか・・・? 関係ない気はするんだけどなぁ・・・。
あぁ、ほんとメモリ管理はめんどくさい・・・;;