前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

13.4. リスト

SFXList クラスは、 双方向リストとして複数の要素を操作するためのデータ構造です。 要素単位でメモリの確保と解放が行われます。

[Note] SFXList と SFXArray

SFXList クラスでは、 要素の挿入と削除は、前後の要素と当該要素のポインタの付け替え操作だけです。 一方、SFXArray クラスでは、 要素の挿入や削除は当該要素以降の要素を内部バッファメモリ内で移動する必要があります。 そのため、要素の挿入や削除は SFXArray クラスよりも高速に行えます。

SFXList クラスでは、 要素の参照はリンクを辿る必要があります。 一方、SFXArray クラスでは、インデックスを使用してダイレクトにアクセスできます。 そのため、要素の参照は SFXArray クラスよりも低速に行われます。

以下は、SInt32 型のデータを要素に持つリストを定義するコードです。

// SInt32 型のデータを要素に持つリストの定義
SFXList<SInt32> list;

// 現在のリストの状態: list = ()

以下のコードでは、 SFXList::InsertLast 関数を使用して配列に 4 つの要素を追加しています。

// 現在のリストの状態: list = ()

list.InsertLast(3);    // リストの場合、追加する要素単位でヒープメモリ領域が確保される
// 現在のリストの状態: list = (3)

list.InsertLast(-15);
// 現在のリストの状態: list = (3, -15)

list.InsertLast(0);
// 現在のリストの状態: list = (3, -15, 0)

list.InsertLast(1003);
// 現在のリストの状態: list = (3, -15, 0, 1003)
[Note] 注意

SFXList::InsertLast 関数を呼び出す度に、 要素のサイズだけヒープメモリ領域が確保されます。 配列では、 クラスター単位でヒープメモリ領域が確保されます。

以下は、SFXList::Insert 関数を使用して要素をリストに挿入するコードです。 配列のように当該要素以降のすべての要素を移動する必要がないので、 要素の挿入は高速に行えます。

// リストに要素を挿入する

// 現在のリストの状態: list = (3, -15, 0, 1003)
// 2 番目の要素の後ろに 99 を挿入する
list.Insert(2, 99);
// 現在のリストの状態: list = (3, -15, 99, 0, 1003)

// 先頭に -100 を挿入する
list.InsertFirst(-100);
// 現在のリストの状態: list = (-100, 3, -15, 99, 0, 1003)

リストのサイズ(要素数)を取得するには、 SFXList::GetSize 関数を呼び出します。

// 現在のリストの状態: list = (-100, 3, -15, 99, 0, 1003)

// リストのサイズ(要素数)を取得する
SInt32 n = list.GetSize();  // n = 6

リストでは、 配列SFXArray::operator[] オペレーターに相当するものは定義されていませんが、 SFXList::Get / SFXList::Set 関数の引数にインデックスを指定して個々の要素にアクセスできます。

[Note] 注意
SFXList::Get / SFXList::Set 関数を利用したリストの要素へのアクセスは、 配列のようなダイレクトアクセスではなく、リスト内の要素のリンクを辿ることになるので、 それだけ時間が掛かります。
// [] オペレーターの代わりに Get/Set 関数を使用してリストの要素にアクセスする

// 現在のリストの状態: list = (-100, 3, -15, 99, 0, 1003)

// リストの 2 番目の要素を取得する
n = list.Get(1);  // n = 3 "n = list[1];" は不可

// リストの 3 番目の要素に 6 を設定する
list.Set(2, 6);  // "list[2] = 6;" は不可

// 現在のリストの状態: list = (-100, 3, 6, 99, 0, 1003)

先頭・末尾の要素は、 SFXList::GetFirst / SFXList::GetLast 関数を使用して取得できます。

// 現在のリストの状態: list = (-100, 3, 6, 99, 0, 1003)

// 先頭の要素を取得する
SInt32 first = list.GetFirst(); // first = -100

// 末尾の要素を取得する
SInt32 last  = list.GetLast();  // last  = 1003

リストの要素を削除するには、 SFXList::Remove 関数を呼び出します。

// 現在のリストの状態: list = (-100, 3, 6, 99, 0, 1003) 

// 4 番目から 5 番目までの要素を削除する
list.Remove(3, 5); 

// 現在のリストの状態: list = (-100, 3, 6, 1003) 
[Note] 注意

要素がポインタ型の場合、 要素を削除してもポインタの指すヒープメモリ領域は解放されません。 メモリリークの原因となるので注意が必要です。

リストのすべての要素を削除するには、 SFXList::Clear 関数を呼び出します。 この関数は、内部バッファを解放します。

// 現在のリストの状態: list = (-100, 3, 6, 1003) 

// リストのすべての要素を削除する
list.Clear(); 

// 現在のリストの状態: list = ()
// 内部のバッファは解放される

以下は、引数に指定した値を持つ要素を検索する、またはそれが存在するか判定するコードです。 SFXList::FirstIndexOf / SFXList::LastIndexOf 関数は、 引数の値を持つ要素を検索し、そのインデックスを取得します。 SFXList::Contains 関数は、 引数の値を持つ要素が存在する否か判定します。

[Tip] Tip

指定したインデックスの要素の値を変更するには、 SFXList::Set 関数を呼び出します。

// 現在のリストの状態: list = ()

// リストに 5 つの要素を追加する
SInt32 i;
for (i = 0; i < 5 ; ++i) {

    list.InsertLast(10 * (i - 2) * (i - 2));
}

// 現在のリストの状態: list = (40, 10, 0, 10, 40)

// 3 番目の要素を 100 に設定する
list.Set(2, 100);

// 現在のリストの状態: list = (40, 10, 100, 10, 40)

SInt32 x;
Bool   b;

// 10 の値を持つ要素の最初のインデックスを検索する
x = list.FirstIndexOf(10);     // x = 1

// 5 の値を持つ要素の最初のインデックスを検索する
x = list.FirstIndexOf(5);      // x = -1: 当該要素が存在しないので -1 が返る

// 10 の値を持つ要素の最後のインデックスを検索する
x = list.LastIndexOf(10);      // x = 3

// 100 の値を持つ要素が存在するか判定する
b = list.Contains(100);        // b = true

// 0 の値を持つ要素が存在するか判定する
b = list.Contains(0);          // b = false

リストの要素を巡回するには、列挙子や反復子を利用します。 反復子を利用する場合は、要素を追加したり、削除することができます。

例 13.5. 列挙子による巡回

SFXList<SInt32>::Enumerator etor = list.GetFirstEnumerator();
SInt32 i(0);

while(etor.HasNext()) {

    SInt32 n = etor.GetNext(); // n に要素が入る

    // n をデバッグウィンドウに表示する
    TRACE("#: %d, Value: %d", i++, n);
}

例 13.6. 反復子による巡回

SFXList<SInt32>::Iterator itor = list.GetFirstIterator();
SInt32 i(0);

while(itor.HasNext()) {

    SInt32 n = itor.GetNext(); // n に要素が入る

    // n をデバッグウィンドウに表示する
    TRACE("#: %d, Value: %d", i++, n);
}