BCB/TList

オブジェクトのリスト保持に良く使われる、TListクラスに関するメモ。

class TList : public System::TObject

std::vectorを使うまでも無いようなデータ管理に。

voidポインタを保持するということで取り出すたびにキャストしなければならないのが不便ですが、VCLに内包されてるので特別にヘッダを読み込まなくても良い手軽さがあります。

目次

概要

TListオブジェクトはポインタの配列を格納します。主な機能は下記のとおり。

  • リストのオブジェクトを追加・削除する。
  • リストのオブジェクトを配列し直す。
  • リストにあるオブジェクトを検索およびアクセスする。
  • リストにあるオブジェクトをソートする。

プロパティ

Capaccity

__property int Capacity = { read=FCapacity, write=FCapacity };

リストに保持するポインタの数を設定する。Capacityは確保済みの数。実際に格納されている数ではない。

実際に格納されている数はCount。従って、Capacity >= Count となる。

Capacityを超えてオブジェクトを追加しようとすると、Capacityを自動的に増加する(再割当)。予め必要数を設定しておくと再割当て回数が減り、性能向上に繋がる。

Capacity設定時にメモリが確保できない場合は、EOutOfMemory例外が発生する。

Count

__property int Count = { read=FCount, write=FCount };

Items配列のエントリ数。

値を増やすとNULLポインタがItems配列の末尾に追加される。減らすと末尾から順に削除される。

Items

__property void *Items = { read=Get, write=Get };

保持しているポインタ配列へアクセスする。Indexにより特定のオブジェクトへポインタが取得・変更できる。

MyList->Items[1] = new AnsiString("ABC");
AnsiString *str = (AnsiString*)MyList->Items[1];

追加はできないので、Addメソッドを使うか、Count値を増やす。

List

_property void * * List = { read = FList };

Items配列に直接アクセスするポインタを返します。

例えばAnsiString型のポインタ配列を保持している時、

AnsiString **items = (AnsiString**)MyList->List;

Memo1->Lines->Add(*items[0]);
Memo1->Lines->Add(*items[1]);
Memo1->Lines->Add(*items[2]);

このように配列として扱うことができます。

メソッド

Add

int Add(void *Item);

Items配列の最後に新しいオブジェクトを追加。追加したオブジェクトのインデックスを戻り値として返す。最初のインデックス値はゼロ。

Count+1、必要ならCapacityもプラスし、メモリを割り当てる。

Assign

void Assign(TList *ListA, TListAssignOp AOperator, TList *ListB);

他のリストの要素を、自身のリストに割り当てる。AOperatorで指定した論理演算子を使ってリストの結合を行う。

ListBがNULLの時、AOperatorで指定した演算子を使って、ListAを自身のリストにマージする。

ListBが非NULLの時、自身のリストをListAに置換え、AOperatorで指定した演算子を使って、ListAを自身のリストにマージする。

TListAssignOpは列挙型。

TListAssignOp 意味
iaAnd ターゲットリストからソースリストに無い全ての要素を削除する。最終的にターゲットリストは2つのリストの交差部分を格納する。
iaCopy ターゲットリストをソースリストで上書きする。
iaDestUnique ターゲットリストからソースリストにある全ての要素を削除する。最終的にターゲットリストは元のターゲットリストに固有の要素を格納する。(iaOr → iaXor と同等)
iaOr ターゲットリストに無い、ソースリストの全ての要素を追加する。最終的にターゲットリストは2つのリストの共通部分を格納する。
iaSrcUnique ターゲットリストをターゲットリストに無いソースリストの要素で置換する。(iaAnd → iaXor と同等)
iaXor ターゲットリストからソースリストにある全ての要素を削除し、元のターゲットリストに無いソースリストの要素を追加する。最終的にターゲットリストはソースリストとターゲットリストの両方に固有の要素を格納する。

Clear

virtual void Clear();

Items配列を空にしCountをゼロにする。また、Capacityもゼロにする。

Delete

void Delete(int Index);

Indexで指定した要素を削除する。以降の要素は繰り上がり、Countが減少。

Capacityは減らさない。

Exchange

void Exchange(int Index1, int Index2);

Items配列内の要素(Index1とIndex2)を入れ替える。

Expand

TList * Expand();

メモリを再確保する。Count == Capacity の場合に有効。

現在のCapacityの値が4以下の場合は+4。8以下ならば+8。それ以上ならば+16増える。

Extract

void * Extract(void *Item);

指定要素をItems配列から削除する。

First / Last

void * First();

Items[0]を返す。

void * Last();

Items[Count-1]を返す。

IndexOf

int IndexOf(void *Item);

指定要素の値を持つインデックスを返す。2つ以上ある場合は最初に登場したものを返す。

見つからない場合は-1を返す。

Insert

void Insert(int Index, void *Item);

Items[Index]の手前に、指定要素を挿入する。つまりItems[Index]以降を後ろへずらし、Items[Index]に指定要素を書き込む。

Move

void Move(int CurIndex, int NewIndex);

CurIndexの項目をNewIndexへ移動する。

Pack

void Pack();

NULLポインタを持つ要素を削除し、詰める。

Remove

int Remove(void *Item);

指定要素をItems配列から削除する。指定要素を複数持つ場合は、最初に見つかったものを対象とする。

項目が削除される前の配列Itemsに対するインデックスを戻り値として返す。

Sort

void Sort(int(_fastcall *)(void *,void*) Compare);

比較関数Compareに基づいてクイックソートを行う。

比較関数のプロトタイプ例

int __fastcall Compare(void *x, void *y);

比較結果を、x<yの時は負、x==yの時はゼロ、x>yの時は正の値として返す。

Notify

virtual void Notify(void *Ptr, TListNotification action);

項目がリストに追加、削除、取得された時に応答するメソッド。

TListNotification列挙型(lnAdded, lnExtracted, lnDeleted)。

サンプルプログラム

簡単な動作を確認できるプログラムを作りました。ソースはこちら

画面イメージ

名前と身長と体重を持つ構造体を保持させてます。追加・削除・全削除・入れ替え・一覧表示の基本操作と、ソート機能が使えます。

また、独自Notifyメソッドを実装することで、追加・削除などの操作に反応させるサンプルも含まれてます。保持データの削除時の後始末などに使えるかと。


2007-04-28 komina