iterator のポインタの移動の順番2006年07月20日 09時36分14秒

自分で Linked-List などのデータストラクチャを書く必要が出来たとする。大概にして、全ての要素を歩いて各要素に処理をするイテレータが必要になる。


void iterator(struct list_t *list,
int (*callback)(void *data, void *extra), void *data)
{
    struct item_t *item = list->head;
    while(item)
    {
        if(!callback(item->data, extra))
            return;
        item = item->next;
    }
}

とやってしまうことが多い。callback 関数は Linked-List に保持している値を data として受け取り、また extra を追加情報として callback に渡せる。なお、callback は戻り値として 0 を返すことにより、イテレータを抜けることも出来る。


int count(void *data, void *extra)
{
    int *count = extra;
    (*count)++;
}

int main()
{
    int num;
...
    iterator(&list, count, &num);
}

などと、list のノードの数を数えることも出来る。

しかし、この itertor() には一つ欠陥がある。free() などの破壊的な callback が使えないのだ。全てのノードを一気に開放することが出来ない。free() をしても動いてしまう行儀の悪いシステムもあるかも知れない。

そこで、以下のように next のポインタを callback を呼ぶ前に取得する。


void iterator(struct list_t *list,
int (*callback)(void *data, void *extra), void *data)
{
    struct item_t *item = list->head;
    while(item)
    {
        struct item_t *next = item->next;
        if(!callback(item->data, extra))
            return;
        item = next;
    }
}

これで、free() など破壊的な操作をする callback も呼ぶことが出来る。