2010年10月23日土曜日

C++ 標準ライブラリ vector を配列で置き換える

動的配列のテンプレートクラスvectorを配列で置き換えてみる。

簡単にコードの説明。

◆ Node クラス
vectorクラス、または配列に格納していく要素として、
インスタンスを利用するために用意した。
vector、または配列に追加する要素はint型でもなんでもよい。

ただし、それぞれのやり方で格納した要素(ここではインスタンス)のメソッドを
呼び出す手段も比較したかったため、クラスを使ったまでである。


◆ Nodes_stl クラス
vectorを使い、要素を加えていく。


◆ Nodes_nonstl クラス
配列を使い、要素を追加していく。



#include <vector>
#include <iostream>
#include <algorithm>

class Node
{
  public:
  Node()
  {
    std::cout<<"constructor"<<std::endl;
  }

  ~Node()
  {
    std::cout<<"destractor"<<std::endl;
  }

  void test()
  {
    std::cout<<"test     : OK"<<std::endl;
  }

  void test_arg(int n)
  {
    std::cout<<"test_arg : OK"<<std::endl;
  }
};


template<typename T>
class Nodes_stl
{
  private:
  std::vector<T *> nodes;

  public:
  void add(T *add)
  {
    nodes.push_back(add);
  }

  void iterator()
  {
    std::for_each(nodes.begin(), nodes.end(), \
      std::mem_fun(&Node::test));
  }

  void iterator_arg()
  {
    std::for_each(nodes.begin(), nodes.end(), \
      std::bind2nd(std::mem_fun(&Node::test_arg), 10));
  }
};


#define MAX_SIZE 10
template<typename T>
class Nodes_nonstl
{
  private:
  T* nodes[MAX_SIZE];
  int num;

  public:
  Nodes_nonstl()
    : num(0)
  {
  }

  void add(T *add)
  {
    if(num >= MAX_SIZE)
    {
      std::cout<<"error"<<std::endl;
      exit(1);
      // 簡単にexitで終了させたが、当然他の実装もある
      // return NULL を返す
      // 例外(throw)を投げる
      // メモリ領域を拡張する
      // などである
    };
    nodes[num++] = add;
  }

  T** begin()
  {
    return nodes;
  };

  T** end()
  {
    return nodes + num;
  };

  void iterator()
  {
    for(Node **p = begin(); p != end(); ++p)
    {
      (*p)->test();
    }
  }

  void iterator_arg()
  {
    for(Node **p = begin(); p != end(); ++p)
    {
      (*p)->test_arg(10);
    }
  }
};

int main()
{
  Node *node1, *node2, *node3;
  node1 = new Node();
  node2 = new Node();
  node3 = new Node();

  // STL
  Nodes_stl<Node> nodes_stl;
  nodes_stl.add(node1);
  nodes_stl.add(node2);
  nodes_stl.add(node3);

  nodes_stl.iterator();
  nodes_stl.iterator_arg();

  // NON STL
  Nodes_nonstl<Node> nodes_nonstl;
  nodes_nonstl.add(node1);
  nodes_nonstl.add(node2);
  nodes_nonstl.add(node3);

  nodes_nonstl.iterator();
  nodes_nonstl.iterator_arg();

  delete node1;
  delete node2;
  delete node3;

  return 0;
}