safty array

3565 ワード

注:後でboostのMulti_を発見arrayは使いやすく、自分で格納方法が行か列か、baseが0か1かを指定することもできます.最も重要なのは、1次元配列と同じポインタで問題を解決できることです.
前回1つの配列の境界を越える問題に出会って調べるのが難しくて、いつもcrashが異なる位置にいて、ちょうど最近fortranからC/C++までの翻訳の仕事をしていて、中にも多くの配列の動作があって、その上配列は多くのパラメータを伝達して、例えば2次元の配列は更に1つのNとMが2つの次元の長さを表すことを伝達して、ちょうど前に本「Optimizing software in C++」を読んだことがありますが、作者は良いパッケージを実現しました.
C動的多次元配列の操作は面倒であり,特に初期化と削除の際には1次元の配列として扱うことが望ましい(以下のコードを参照).
#include <memory.h>                              // For memcpy and memset
#include <stdio.h>                               // Needed for example only
#include <malloc.h>

// Template for safe array with bounds checking
template <typename T, unsigned int N> class SafeArray {
   T a[N];                             // Array with N elements of type T
public:
   // Constructor
   SafeArray() {
      memset(a, 0, sizeof(a));         // Initialize array to zero
   }
   // Return the size of the array
   int Size() const {
      return N;
   }
   // Safe [] array index operator
   T & operator[] (unsigned int i) {
      if (i >= N) {
         // Index out of range. The next line provokes an error.
         // You may insert any other error reporting here:
         return *(T*)0;  // Return a null reference to provoke error
      }
      // No error
      return a[i];     // Return reference to a[i]
   }
};


template <typename T> class SafeDynamicArray {
   T* a;
   unsigned int N; // Array with N elements of type T
public:
   // Constructor
   SafeDynamicArray(unsigned int size) : N(size){
        a=(T*)calloc(N, sizeof(T));
   }
    ~SafeDynamicArray(){ if(a) delete[] a; }
    SafeDynamicArray& operator=(const SafeDynamicArray<T>& rhs){
        if(&rhs == this) return *this;
        delete[] a;
        a = calloc(rhs.Size(), sizeof(T));
        memcpy(a, rhs[0],sizeof(T)*rhs.Size());
        return *this;
    }

   // Return the size of the array
   int Size() const {
      return N;
   }
   // Safe [] array index operator
   T & operator[] (unsigned int i) {
      if (i >= N) {
         // Index out of range. The next line provokes an error.
         // You may insert any other error reporting here:
         return *(T*)0;  // Return a null reference to provoke error
      }
      // No error
      return a[i];     // Return reference to a[i]
   }
};
template <typename T> class Array2D{
    SafeDynamicArray<T>*    _data;
    int _row;
    int _col;
public:
    Array2D(int row, int col):_row(row), _col(col){
        _data= new SafeDynamicArray<T>(_row*_col);
    }
    ~Array2D(){if(_data) delete _data; }

    T& at(int i, int j){ // base 0,0
        int index=i*_col+j;
        return (*_data)[index];
    }

    int row()const{return _row; }
    int col()const{return _col; }

    Array2D& operator=(const Array2D<T>& rhs){
        if(&rhs == this) return *this;
        delete[] _data;
        _data= new SafeDynamicArray<T>(rhs.row()*rhs.col());
        _data->operator=(*(rhs._data));
        return *this;
    }
};