Vector コンテナ入門

Vector コンテナの元となる Object Class をコーディングします。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. template を使って Vector Container の元となる Object Class をコーディングしてみましょう。
    プログラムの作成に当たっては、これまで説明したC++言語と STL の知識が必要です。
    vector Container は配列のようなものですが、配列よりも柔軟性に富み、大きさをダイナミックに変更することが出来ます。
    また Vector は他のコンテナと違って、配列と同じように cell(要素)を添え字で参照出来ることが特徴です。
    これらの機能をどのようにプログラミングすれば実現出来るかを学んで下さい。
    実際の vector Container は多くの機能を備えていてソースコードも膨大ですが、ここではステップアップでその基本に迫って行きましょう。
  2. Vector をテストする Main Program(VectorTest.cpp)です。
    Vector Container のヘッダファイル "Vector.h" をインクルードします。
    STL のベクターは vector ですが、こちらは Vector になっています。
    /*★ Main Program  Step1    前田  稔 ★*/
    #include <iostream>
    #include "Vector.h"
    using namespace std;
    
    void main()
    {
        Vector<int> v;
        cout << "正常にコンパイルされることを確認します" << endl;
    }
    
  3. template を使って Vector Class を定義した Vector.h ファイルです。
    STL のベクターは vector ですが、こちらは Vector になっています。
    template を使った Object Class の基礎は Template Object Class を参照して下さい。
    typedef で定義されている iterator, reference はイテレータの型宣言で、後で詳しく説明します。
    コンストラクタでは Vector の大きさ(vsize)と初期値(v)をパラメータで受け取ります。
    規定値では vsize, v ともゼロになっています。
    array_size は Vector として割り当てられた領域のサイズで、current_size は実際に使用されているサイズです。
    new T[array_size+1] で連続したメモリ領域を割り当てます。
    このとき end() が指す iterator を作るために1を加えています。
    Vector は配列と同じように cell(要素)を添え字で参照するので、領域が連続していなければなりません。
    Vector を添え字で参照するために、演算子([ ])をオーバーロードしている事に注目して下さい。
    詳細は 演算子のオーバーロード を参照して下さい。
    iterator array; が割り当てられたメモリ領域の先頭ポインタです。
    /*★ Vector Class Step1    前田  稔 ★*/
    #ifndef VECTOR_H
    #define VECTOR_H
    
    #include<iostream>
    using namespace std;
    
    template<class T>
    class Vector
    { public:
        typedef T* iterator;
        typedef T& reference;
    
        // コンストラクタ
        Vector(int vsize=0, const T& v=T())
        {   array_size   = vsize;
            current_size = vsize;
            array        = new T[array_size+1];     // end() のために1を追加
            for(int i= 0; i<vsize; i++) array[i] = v;
        }
    
        // デストラクタ
        ~Vector()
        {   delete [] array;
        }
    
        //添え字演算子関数
        reference operator[](int index) { return array[index]; }
    
    private:
        iterator array;
        int current_size;
        int array_size;
    };
    #endif
    

【演習】

  1. VectorTest.cpp で Vector に数値を格納して表示します。
    Vector<int> v1(5,123); で、5件分の領域を初期値 123 で確保して表示します。
    v1[i] = i+10; で配列と同じように添え字で参照できることを確かめて下さい。
        int i;
        Vector<int> v1(5,123);
    
        for(i= 0; i<3; i++) v1[i] = i+10;
        cout << "v1  ";
        for(i= 0; i<5; i++) cout << v1[i] << "  ";
        cout << endl;
        
  2. Vector<int> v2(10); で、10件分の領域を初期値を指定しないで確保します。
    v2 には初期値を設定していないので、先頭から7個の領域に 20-i を格納しました。
        Vector<int> v2(10);
    
        for(i= 0; i<7; i++) v2[i] = 20-i;
        cout << "v2  ";
        for(i= 0; i<10; i++) cout << v2[i] << "  ";
        cout << endl;
        
  3. VectorTest.cpp では Vector に割り当たデータの個数でループしています。
    for(i= 0; i<5; i++) cout << v1[i] << " ";
    for(i= 0; i<10; i++) cout << v2[i] << " ";
    これでは Vector を使う側でデータの個数を把握しなければなりません。
    現在使われているデータの数は Vector Class の current_size で管理されているので、この値を使うのが合理的でしょう。
    但し current_size は private: なので直接参照することは出来ません。
    そこでサイズとキャパシティーを取得するメンバー関数を Vector Class に追加します。
    この関数は簡単なのでインライン関数として定義して下さい。
    インライン関数の説明は inline 関数 を参照して下さい。
    int size() { return current_size; }
    int capacity() { return array_size; }
    size() 関数を使うと先のコーディングは次のようになります。
    for(i= 0; i<v1.size(); i++) cout << v1[i] << " ";
    for(i= 0; i<v2.size(); i++) cout << v2[i] << " ";
  4. キャパシティーはヒープメモリ上に割り当てられた cell(データ)の個数で、サイズは現在使われている cell の数です。
    VectorTest.cpp でこの値を確認してみましょう。
    cout << "v1キャパシティー= " << v1.capacity() << " v1サイズ= " << v1.size() << endl;
    cout << "v2キャパシティー= " << v2.capacity() << " v2サイズ= " << v2.size() << endl;
  5. 先頭のデータを取得するメンバ関数 front() と最後尾のデータを取得するメンバ関数 back() を追加して下さい。
    この関数も簡単なのでインライン関数として定義して下さい。
    関数の型は typedef で定義した reference を使います。
    reference front()
    {
    }
    reference back()
    {
    }
    VectorTest.cpp で front() と back() を使って先頭のデータと最後尾のデータを印字して下さい。
    cout << "front= " << v1.front() << " back= " << v1.back();
    cout << endl;

超初心者のプログラム入門(C/C++)