2018年10月15日月曜日

[MQL4] CArrayObj と CList の違い

`include/Arrays` 以下にはオブジェクトを格納できる [CArrayObj](https://www.mql5.com/en/docs/standardlibrary/datastructures/carrayobj) と [CList](https://www.mql5.com/en/docs/standardlibrary/datastructures/clist) が定義されています。
どちらも大体同じような機能を提供しているのですが、何が違うのか見てみました。

結論から言うと、`CArrayObj` の方は内部で配列を持っているのに対し、`CList` は [CObject](https://www.mql5.com/en/docs/standardlibrary/cobject) の持つリンクリスト機能を使っています。

### CArrayObj
`CArrayObj` は一般的な配列同様に使用できます。
ランダムアクセスする場合などはこちらを使うと良いでしょう。

> 参考
>
> [MQL4 で可変長配列を使用する方法 | Strategy of C](https://strategyofc.blogspot.com/2018/10/mql4.html)

### CList
`CList` は内部にポジションを持っており、`GetNextNode()` のようにイテレーティブな処理をする場合、高速に処理できます。

全要素に対して一気に処理をかけるような処理に向いています。

以下に簡単な例を挙げます。

```mq4
#property strict
 
#include <Object.mqh>
#include <Arrays/List.mqh>
 
class Item : public CObject {
private:
    const int m_value;
 
public:
    Item(int value) : m_value(value) {
    }
 
    virtual ~Item() {
    }
 
    int GetValue() const {
        return m_value;
    }
 
    virtual int Compare(const CObject *node, const int mode=0) const {
        int diff = this.GetValue() - dynamic_cast(node).GetValue();
        return (diff == 0) ? 0 : (diff > 0) ? 1 : -1;
    }
};
 
CList m_item_list;
 
void OnStart()
{
    for (int i = 0; i < 10; i++) {
        int value = (i % 2 == 0) ? i : i + 10;
        m_item_list.Add(new Item(value));
    }    
 
    // 内部ポインタを最初にもどす
    m_item_list.MoveToIndex(0);
    
    Item* item;
    // 「最後まで一気に処理する」みたいなのに向いている
    while ((item = m_item_list.GetNextNode()) != NULL) {
        printf("%d", item.GetValue());
    }
}
```

なお、`CList` も `CArrayObj` と同様、Sort 済みでないと検索が出来ません。
また、`Compare()` の実装によっては検索結果が想定外になることもあるので気をつけてください。

> 参考
>
> [[MQL4] CArrayObj はソート済みじゃないと Search() の結果が -1 になってしまう](https://strategyofc.blogspot.com/2018/10/mql4-carrayobj-search-1.html)