Re: Dynamic array advice.
I am crating a new version of my map game and my map will be a 2d
array. I had problems trying to create a 2d array dynamically, in
fact C++ won't let me do it. My question is how to create the size of
array I need at run time without using too much memory or going over
the allotted size if I choose to use this object for a different
game.
One idea I have is to create space * spaces = new space[len*with];
then have all my accessors just convert x and y to:
void place(int x, int y){spaces[x*len+y;}
I am getting rather tired of complaints about not being able to do 2-D arrays.
Here is a multidimensional array class derived from std::vector that I wrote and
have used for many years. It is not optimal, but is close enough for all but the
most time intensive programs.
If this not sufficient, the I would suggest using the Boost::multiarray.
//======================== Array.h ===============================
#ifndef GPD_Array_H
#define GPD_Array_H
//**** Includes ****
#include <vector>
#include <cstdlib>
#include <cstdarg>
//**** Uses ****
using std::vector;
namespace GPD {
template<typename T_, int ND> class ArrayBase: public vector<T_> {
public:// Defs
typedef typename vector<T_>::iterator IterArr;
public:// Uses
using vector<T_>::begin;
using vector<T_>::end;
using vector<T_>::size;
public:// Constructors
ArrayBase(): vector<T_>() {}
ArrayBase(int Len): vector<T_>(Len) {}
ArrayBase(const ArrayBase& a): vector<T_>(a) {(*this) = a;}
public:// Destructor
virtual ~ArrayBase() {}
public:// Functions
int Dim(int N) const {return int(dim[N]);}
ArrayBase& operator=(const ArrayBase& a) {
vector<T_>::operator=(a);
copy(&a.dim[0], &a.dim[ND], &dim[0]);
copy(&a.sizeDim[0], &a.sizeDim[ND], &sizeDim[0]);
iData = begin();
return (*this);
}
protected:// Variables
size_t dim[ND];
size_t sizeDim[ND];
IterArr iData;
};
template<typename T_, int ND> class SubArr {
private:// Defs
typedef typename ArrayBase<T_, ND>::iterator IterArr;
public:// Constructors
SubArr<T_, ND>(const IterArr IStart, const size_t* ArrSizeDim):
sizeDim(ArrSizeDim), iElem(IStart) {}
public:// Functions
SubArr<T_, ND-1> operator[](size_t K) const {
return SubArr<T_, ND-1>((iElem+K*sizeDim[0]),
(sizeDim+1));
}
private:// Variables
const size_t* sizeDim;
IterArr iElem;
};
template<typename T_> class SubArr<T_, 1> {
private:// Defs
typedef typename ArrayBase<T_, 1>::iterator IterArr;
public:// Constructors
SubArr(const IterArr IStart, const size_t* ArrSizeDim):
sizeDim(ArrSizeDim), iElem(IStart) {}
public:// Functions
T_& operator[](size_t K) const {return (*(iElem+K));}
private:// Variables
const size_t* sizeDim;
IterArr iElem;
};
template<typename T_, int ND=1> class Array: public ArrayBase<T_, ND> {
public:// Defs
typedef typename Array<T_, ND>::iterator IterArr;
public:// Uses
using vector<T_>::begin;
using vector<T_>::end;
using vector<T_>::size;
using ArrayBase<T_, ND>::sizeDim;
using ArrayBase<T_, ND>::dim;
using ArrayBase<T_, ND>::iData;
public:// Constructors
Array<T_, ND>(): ArrayBase<T_, ND>() {}
Array<T_, ND>(const Array<T_, ND>& a): ArrayBase<T_, ND>(a) {}
Array<T_, ND>(size_t D1, ...) {
// Initialize array dimensions and compute total array size
va_list ListDims;
va_start(ListDims, D1);
sizeDim[0] = 1;
for (int N = 0; N < ND; N++) {
dim[N] = (N ? va_arg(ListDims, int) : D1);
sizeDim[0] *= dim[N];
}
va_end(ListDims);
// Initialize array subspace sizes
for (int N = 1; N < ND; N++) {
sizeDim[N] = sizeDim[N-1] / dim[N-1];
}
// Allocate memory for data array
resize(sizeDim[0]);
iData = begin();
}
public:// Functions
void clear() const {return vector<T_>::clear();}
int Size() const {return int(size());}
void Resize(size_t D1, ...) {
// Initialize array dimensions and compute total size
va_list ListDims;
va_start(ListDims, D1);
sizeDim[0] = 1;
for (int N = 0; N < ND; N++) {
dim[N] = (N ? va_arg(ListDims, int) : D1);
sizeDim[0] *= dim[N];
}
va_end(ListDims);
// Initialize array subspace sizes
for (int N = 1; N < ND; N++) {
sizeDim[N] = sizeDim[N-1] / dim[N-1];
}
// Allocate memory for data array
resize(sizeDim[0]);
iData = begin();
}
void Clear() {
clear();
for (int N = 1; N < ND; N++) {
sizeDim[N] = 0;
}
}
void Fill(const T_& val) {
for (IterArr IT = begin(); IT < end(); IT++) {
(*IT) = val;
}
}
public:// Functions
SubArr<T_, ND-1> operator[](size_t K) const {
return SubArr<T_, ND-1>((iData+K*sizeDim[1]),
(sizeDim+2));
}
};
template<typename T_> class Array<T_, 1>: public ArrayBase<T_, 1> {
public:// Constructors
Array(): ArrayBase<T_, 1>() {}
Array(size_t Len): ArrayBase<T_, 1>(Len) {}
Array(const ArrayBase<T_, 1>& a): ArrayBase<T_, 1>(a) {}
};
}
#endif
//======================== Test Program ===============================
//**** Includes****
#include "Array.h"
#include <iostream>
//**** Uses ****
using std::cout;
using std::endl;
using GPD::Array;
int main() {
cout << "Start Array Test: " << endl;
Array<float,3> a(3,2,5);
for (int N0 = 0; N0 < a.Dim(0); N0++) {
for (int N1 = 0; N1 < a.Dim(1); N1++) {
for (int N2 = 0; N2 < a.Dim(2); N2++) {
a[N0][N1][N2] = 100*(N0+1) + 10*(N1+1) + (N2+1);
cout << a[N0][N1][N2] << endl;
}
}
}
return 0;
}