C++の新しいキャスト
Monday, April 2nd, 2007従来のキャストの問題点
異なる型への変換において、C/C++ではキャストが用いられます。
// intからlongへのキャスト int ival; int lval = (long)ival;
ご存知のとおり、キャストは非常に危険です。 本来ならば型の不一致によるコンパイルエラーをねじ伏せるのですから。
異なる型への変換において、C/C++ではキャストが用いられます。
// intからlongへのキャスト int ival; int lval = (long)ival;
ご存知のとおり、キャストは非常に危険です。 本来ならば型の不一致によるコンパイルエラーをねじ伏せるのですから。
Cではsizeofによって構造体がメモリ上で占める大きさ(バイト数)を知ることができます。
struct s{
int x;
int y;
};
...
cout << sizeof(s) << endl;
僕の愛用する処理系、Visual C++ 6.0では 8が得られました。intひとつにつき4byteを消費するからでしょう。
それではC++でのclassの大きさはどうでしょう。内包するメンバ変数それぞれの占めるバイト数の総和になるのでしょうか。
をオブジェクト指向の三本柱などと称しています。その中でも抽象データ型(あるいはデータの抽象化)はオブジェクト指向の最も基本的で重要な概念ではないかと考えます。
"データを抽象化する"とは、データをそれに対して適用できる操作の集合で定義することです。
簡単な例として"カウンタ"を考えてみましょう。カウンタには3つの操作:
を提供させることにします。
さて、このカウンタをCで実現するとどうなるでしょうか…
選択チャートには、コレクションに格納するデータについての質問が含まれています。選択チャートにざっと目を通すことにより、作成するプログラムとそのデータにどの Tools.h++ コレクションが最適であるかが分かります。
選択チャートを見やすくするために、各選択肢の質問は簡潔になっています。次に、選択肢の質問について解説します。
コレクションの中には、コレクション内のデータの位置を制御できるものがあります。例えば、配列やベクトル、およびリンクリストはデータを「順序付きで」提示します。特定の順序で、または数値インデックスに基づいてデータにアクセスする必要がある場合、順序には意味があります。
コレクションの中には、コレクション内にすでに存在している項目と等しい項目を挿入できないものがあります (通常、この種のコレクションはセットと呼ばれます)。別の種類のコレクションには、複数の同一項目を保持する様々な方法があり、重複項目の挿入を許可します。Tools.h++ コレクションには、重複を調べる機構と重複項目を保持する機構の両方が備えられています。
コレクション内のデータがそれを挿入する方法によって制御される場合は、「順序が外部的に決定される」と言います。例えば、ベクトルやリンクリストは、外部的に順序付けられています。データがコレクションによって使用されるアルゴリズムによって決定された位置に格納される場合は、順序付けは「本質的」です。例えば、格納されたベクトルやバランスツリーは本質的な順序を持ちます。
値とは異なるキーを基準にして値にアクセスする場合、「外部キーによってデータにアクセスする」と言います。例えば、「電話番号リスト」は、電話番号というデータを、名前の形式をとったキーに関連付けます。逆に、「委員会メンバのリスト」は、名前の形をとったデータだけになります。情報を取得するためには、キーを必要としません。
配列またはベクトルに格納されているオブジェクトには、数値インデックスでアクセスします。例えば、数値インデックス「12」を用いてオブジェクトを見つけ、12
という位置にあるオブジェクトにアクセスします。
明示的なインデックスやキーのいずれとも一緒に格納されていないデータは、検索データとコレクション内のデータの一致を探すことによって見つけることができます。前述した委員会メンバのリストは、この種類のデータの例です。Set や Bag は自身との比較によってアクセスするコレクションの例です。
自身との比較によってデータにアクセスする場合は、どの種類の一致基準を使用するかを知る必要があります。一致には、あるオブジェクトを別のオブジェクトと直接比較する「等値性」を基準にすることも、オブジェクトのアドレスを比較し、オブジェクトが同一であるかどうかを調べる「アイデンティティ」を基準にすることもできます。
リンクノードを利用するコレクションは、通常リストと呼ばれます。リストでは、コレクションの両端にあるデータに素早くアクセスでき、コレクションの真ん中にデータを効率よく挿入することができます。ただし、コレクションの真ん中にあるデータに頻繁にアクセスする必要がある場合、リストは他のコレクションに比べてそれほど効率的ではありません。
処理しなければならないデータの量が分からない場合は頻繁にありますが、処理するほとんどのデータは、コレクションの最も新しいデータか、最も古いデータです。最後に追加されたデータを処理するのに最も効率的なのは、「後入れ先出し」方式を持つコレクションです。後入れ先出し (LIFO) のコンテナは「スタック」です。先入れ先出し (FIFO) 方式でデータを処理するコレクションは、「待ち行列」と呼ばれます。最新データと最古データの両方に効率的にアクセスできるコレクションは、「両頭列」あるいは Deque (Double Ended Queue) と呼ばれます。
一重リンクリストはサイズが小さいのですが、リストの「正面」からだけアクセスできます。二重リンクリストは、より柔軟性のあるアクセス方式を持ちますが、格納されている各オブジェクトごとに追加のポインタを必要とします。
コレクションに格納する項目の最大数があらかじめ分かっている場合は、固定サイズのコレクションを選択する方がより効率的に挿入と削除を行うことができます。反対に、ほとんど無制限に拡張する必要がある場合は、現在格納しているデータ量に合わせて自動的にサイズを調整するコレクションを選択するべきです。
どのコレクションを選択するかは、これまでの経験や直観を含め、数多くの要素に依存します。選択チャートの質問の他に、どのコレクションを選択するかを決める上で次の質問も考慮してください。
「はい」の場合は、ポインタベースのコレクションを使用します。
「はい」の場合は、ポインタベースのコレクションを使用します。
「いいえ」の場合は、値ベースのコレクションを使用します。
「はい」の場合は、ベクトルやリストなどのシーケンスコレクションを使用します。
「はい」の場合は、シーケンスコレクションまたはマッピング (辞書) コレクションを使用します。マップと辞書は、不変のキーを持ちますが、値は変更可能です。
「はい」の場合は、セット、マップ、あるいはソート済みコレクションを使用します。
「はい」の場合は、シーケンスコレクションまたはソート済みコレクションを使用します。
「はい」の場合は、マップまたは辞書を使用します。
「はい」の場合は、セット、マップ、あるいはハッシュベースのコレクションを使用します。
「はい」の場合は、ハッシュベースのコレクションを使用します。
「はい」の場合は、B-ツリー、あるいは新しい標準 C++ ライブラリを基にした連想コンテナを使用します。
RWBTreeOnDisk または RWTValVirtualArray を使用します。
具体クラスは、以下のクラスから構成されています。:
Tools.h++ には、軽量化された単純クラスが多く含まれています。軽量化されたクラスとは、時間のかからない初期設定子とコピーコンストラクタを持つクラスを意味します。単純クラスには、RWDate (日付)、 RWTime(時刻、各種の時間帯および地域に対応)、RWCString (シングルおよびマルチバイト文字列)、RWWString (ワイド文字)、および RWCRegexp または RWCRexpr (正規表現) などがあります。これらのクラスのほとんどは、4バイト以下で保持することができ、また非常に簡単なコピーコンストラクタ(通常1ビットコピー)を持ち、仮想関数は持っていません。Tools.h++ Class Referenceを参照してください。
テンプレートベースのコレクションクラス (略してテンプレート) には、速度と型保証という利点があります。しかし、コードサイズを減らすためには、あまり使わないようにしてください。テンプレートは多くの異なる型で使用できますが、各型がまったく新しいクラスを生成するために、コードサイズが大きくなる可能性があります。使用コンパイラで標準 C++ ライブラリが使える場合は、標準 C++ ライブラリをもとにしている Tools.h++ テンプレートベースコレクションを使用できます。使用コンパイラで標準 C++ ライブラリを使えない場合でも、11.3.1節および 11.10 節に説明されている、サブセットのテンプレートを使用できます。
汎用コレクションクラスは、C++ コンパイラに付属しているプリプロセッサマクロ<generic.h> を使用するクラスです。このクラスは、テンプレートに対応していないコンパイラに対しては、型保証がされているために、テンプレートとほとんど同じように扱えます。このため、移植性が高いとも言えます。ただし、プリプロセッサにかなり依存しているため、この汎用コレクションクラスを含むコードで、デバッガを使用することが困難になる場合があります。さらに詳しくは、第 12 章を参照してください。
Tools.h++ には、抽象基底クラスといろいろな機能のフレームワークを提供する特殊化クラスが含まれています。以下の表は、機能と抽象基底クラスの関係を示したものです。抽象基底クラスの場合は、Tools.h++ Class Referenceの各クラスごとの説明に明記されています。