多倍長整数クラスの作成 [2日目]
代入演算子の場合は自身を返すことで新たにインスタンスが作られませんが、関係演算子の場合は自身の変数を書き換えずに、計算した結果を自身の型で返す為に、一度インスタンスを作って、計算をしてから return をするのですが、returnの時にコピーコンストラクタが実行されて、無駄にインスタンスが作られてしまいます。
JavaやC#ならこういった悩みがないので、C++を触ると面倒な事が多すぎて、C#などの新しい言語の有難味が分かります。
せっかくの論理演算のみで作る多倍長整数型クラスなのに、小さなオーバーヘッドが後々問題になりかねません。
なんとかならないものか・・・・
ちなみにこのクラスは bitboard に使用する為に設計(はたして設計というのか)しました。
このクラスには小さなオーバーヘッドを残さないようにしたいです。
また、28個くらい定義している演算子のオーバーロードはすべて論理演算と基本的な + と - で作る予定です。
尚、+ や - などはキャリーフラグを算出する方法が思いつかないので、インラインアセンブラを使うかもしれません。
■ヘッダ
#pragma once #include <string> using namespace std; namespace BoardGames { /// 数独の数字1つに対する情報 class Plate { private: unsigned long bits[3]; // 初期化 void init(void); // ビットの左右逆転 inline unsigned long rev(unsigned long x); public: Plate(); Plate(int bit1, int bit2, int bit3); Plate(const Plate &plate); #ifdef _DEBUG // テストコード用 string getAscii(); #endif // インデクサ代わり(?) unsigned long operator[](int num); // 代入operator void operator=(const Plate& plate); // 代入演算子 Plate& operator>>=(int n); Plate& operator<<=(int n); Plate& operator&=(const Plate& p); Plate& operator|=(const Plate& p); Plate& operator^=(const Plate& p); Plate& operator+=(const Plate& p); Plate& operator-=(const Plate& p); Plate& operator*=(const Plate& p); Plate& operator/=(const Plate& p); //Plate& operator%=(const Plate& p); // 単項演算子 friend Plate operator!(const Plate& p); friend Plate operator~(const Plate& p); // 二項演算子 Plate operator>>(int n) const; Plate operator<<(int n) const; friend Plate operator&(const Plate& pl, const Plate& pr); friend Plate operator|(const Plate& pl, const Plate& pr); friend Plate operator^(const Plate& pl, const Plate& pr); friend Plate operator+(const Plate& pl, const Plate& pr); friend Plate operator-(const Plate& pl, const Plate& pr); friend Plate operator*(const Plate& pl, const Plate& pr); friend Plate operator/(const Plate& pl, const Plate& pr); //friend Plate operator%(const Plate& pl, const Plate& pr); // 比較 bool operator<=(const Plate& p) const; bool operator>=(const Plate& p) const; bool operator<(const Plate& p) const; bool operator>(const Plate& p) const; bool operator==(const Plate& p) const; bool operator!=(const Plate& p) const; }; }
■コード
#include "default.h" using namespace std; using namespace BoardGames; ///////////////////////////////////////////////////////////////////////////////////// // コンストラクタ ///////////////////////////////////////////////////////////////////////////////////// Plate::Plate() { init(); } Plate::Plate(int bit1, int bit2, int bit3) { init(); bits[2] = bit1; bits[1] = bit2; bits[0] = bit3; } Plate::Plate(const Plate &plate) { init(); bits[0] = plate.bits[0]; bits[1] = plate.bits[1]; bits[2] = plate.bits[2]; } ///////////////////////////////////////////////////////////////////////////////////// // その他内部関数 ///////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG string Plate::getAscii() { string ascii; unsigned long temp = 0; for (int i = 2; 0 <= i; i--) { temp = rev(bits[i]); for (int j = 0; j < 32; j++) { ascii += (char)((temp & 1) + 0x30); temp >>= 1; } } return ascii; } #endif // 初期化 void Plate::init(void) { bits[0] = 0; bits[1] = 0; bits[2] = 0; } // bitの左右逆転 inline unsigned long Plate::rev(unsigned long x) { x = (x & 0x55555555) << 1 | (x >> 1) & 0x55555555; x = (x & 0x33333333) << 2 | (x >> 2) & 0x33333333; x = (x & 0x0f0f0f0f) << 4 | (x >> 4) & 0x0f0f0f0f; x = (x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24); return x; } ///////////////////////////////////////////////////////////////////////////////////// // operator 関係演算子以外 ///////////////////////////////////////////////////////////////////////////////////// unsigned long Plate::operator[](int num) { if (0 <= num && num <= 2) { return this->bits[num]; } return 0; } // 代入演算子 void Plate::operator=(const Plate& plate) { bits[0] = plate.bits[0]; bits[1] = plate.bits[1]; bits[2] = plate.bits[2]; } ///////////////////////////////////////////////////////////////////////////////////// // operator 単項演算子 ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// // operator 二項演算子 ///////////////////////////////////////////////////////////////////////////////////// Plate Plate::operator>>(int n) const { Plate temp(*this); // インスタンスを作成 temp >>= n; return temp; // return時に再度インスタンスが作られる(何とかならないものか・・・・) } Plate Plate::operator<<(int n) const { Plate temp(*this); temp <<= n; return temp; } Plate& Plate::operator>>=(int n) { for (;31<n;n-=31) { ((*this) >>= 31); } bits[0] = (bits[0] >> n) | (bits[1] << (32-n)); bits[1] = (bits[1] >> n) | (bits[2] << (32-n)); bits[2] = bits[2] >> n; return *this; } Plate& Plate::operator<<=(int n) { for (;31<n;n-=31) { ((*this) <<= 31); } bits[0] = bits[0] << n; bits[1] = (bits[1] << n) | (bits[0] >> (32-n)); bits[2] = (bits[2] << n) | (bits[1] >> (32-n)); return *this; }