434,786 Members | 1,131 Online
Need help? Post your question and get tips & solutions from a community of 434,786 IT Pros & Developers. It's quick & easy.

 P: n/a 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;} Mar 3 '07 #1
9 Replies

 P: n/a JoeC wrote: 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;} That would work. There are other lots of other approaches. The classic is (and simplest) to use double pointers space** spaces = new space*[width]; for (int i = 0; i < width; ++i) spaces[i] = new space[length]; then you can just say space[i][j] = whatever; and when you want to free the memory, do the reverse for (int i = 0; i < width; ++i) delete[] spaces[i]; delete[] spaces; john Mar 3 '07 #2

 P: n/a 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 #include #include //**** Uses **** using std::vector; namespace GPD { template::iterator IterArr; public:// Uses using vector::begin; using vector::end; using vector::size; public:// Constructors ArrayBase(): vector() {} ArrayBase(int Len): vector(Len) {} ArrayBase(const ArrayBase& a): vector(a) {(*this) = a;} public:// Destructor virtual ~ArrayBase() {} public:// Functions int Dim(int N) const {return int(dim[N]);} ArrayBase& operator=(const ArrayBase& a) { vector::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::iterator IterArr; public:// Constructors SubArr(const IterArr IStart, const size_t* ArrSizeDim): sizeDim(ArrSizeDim), iElem(IStart) {} public:// Functions SubArr((iElem+K*sizeDim[0]), (sizeDim+1)); } private:// Variables const size_t* sizeDim; IterArr iElem; }; template::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::iterator IterArr; public:// Uses using vector::begin; using vector::end; using vector::size; using ArrayBase::sizeDim; using ArrayBase::dim; using ArrayBase::iData; public:// Constructors Array(): ArrayBase() {} Array(const Array& a): ArrayBase(a) {} Array(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::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((iData+K*sizeDim[1]), (sizeDim+2)); } }; template: public ArrayBase() {} Array(size_t Len): ArrayBase(Len) {} Array(const ArrayBase& a): ArrayBase(a) {} }; } #endif //======================== Test Program =============================== //**** Includes**** #include "Array.h" #include //**** Uses **** using std::cout; using std::endl; using GPD::Array; int main() { cout << "Start Array Test: " << endl; Array

 P: n/a John Harrison wrote: JoeC wrote: >I am crating a new version of my map game and my map will be a 2darray. I had problems trying to create a 2d array dynamically, infact C++ won't let me do it. My question is how to create the size ofarray I need at run time without using too much memory or going overthe allotted size if I choose to use this object for a differentgame.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;} You might want to put that into a class with an overloaded operator(): int & operator( std::size_t row, std::size_t col ) { return ( the_data [ col_size * row + col ] ); } and you could add a const version too: int const & operator( std::size_t row, std::size_t col ) const { return ( the_data [ col_size * row + col ] ); } You also might make the member the_data a std::vector. In that case, you would not even have to take care of your own assignment operator, copy constructor and destructor. E.g:. [code not tested/compiled] template class array2d { std::size_t the_row_size; std::size_t the_col_size; std::vector> That would work. There are other lots of other approaches. The classic is (and simplest) to use double pointers space** spaces = new space*[width]; for (int i = 0; i < width; ++i) spaces[i] = new space[length]; then you can just say space[i][j] = whatever; and when you want to free the memory, do the reverse for (int i = 0; i < width; ++i) delete[] spaces[i]; delete[] spaces; I doubt that this is the _simplest_ approach. Once you want an exception safe version, you will find that it is not that simple at all. Any new in the for-loop might throw. In order not to leak, you need to keep track of that and delete the previously allocated rows. The idea of the OP is much easier to implement properly. Best Kai-Uwe Bux Mar 3 '07 #4

 P: n/a On Mar 3, 2:31 pm, John Harrison

 P: n/a On 3 Mar, 21:53, Doyle Rhynard #include #include //**** Uses **** using std::vector; That's not a good thing to have in the header. Remove it and fully qualify vector (i.e. type std::vector) throughout the header. //======================== Test Program =============================== //**** Includes**** #include "Array.h" With your header above, your program (and the OP's program if he uses your code, and every other program that ever uses your code) now has using std::vector forced upon it. That entirely defeats the purpose of vector being in the std namespace. Using declarations and directives have pros and cons that must be considered on a case by case basis. To have the decision forced upon you, particularly by a such a generic concept as a multi-dimensional array that has potential uses far beyond the program it was originally created for, is a Bad Thing. And it can easily be avoided by the one-off cost of a little extra typing up front by fully qualifying the names in the header. Gavin Deane Mar 3 '07 #6

 P: n/a Kai-Uwe Bux wrote: John Harrison wrote: >JoeC wrote: >>I am crating a new version of my map game and my map will be a 2darray. I had problems trying to create a 2d array dynamically, infact C++ won't let me do it. My question is how to create the size ofarray I need at run time without using too much memory or going overthe allotted size if I choose to use this object for a differentgame.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;} You might want to put that into a class with an overloaded operator(): int & operator( std::size_t row, std::size_t col ) { return ( the_data [ col_size * row + col ] ); } and you could add a const version too: int const & operator( std::size_t row, std::size_t col ) const { return ( the_data [ col_size * row + col ] ); } You also might make the member the_data a std::vector. In that case, you would not even have to take care of your own assignment operator, copy constructor and destructor. E.g:. [code not tested/compiled] template class array2d { std::size_t the_row_size; std::size_t the_col_size; std::vector

 P: n/a red floyd wrote: Kai-Uwe Bux wrote: John Harrison wrote: JoeC wrote:I am crating a new version of my map game and my map will be a 2darray. I had problems trying to create a 2d array dynamically, infact C++ won't let me do it. My question is how to create the size ofarray I need at run time without using too much memory or going overthe allotted size if I choose to use this object for a differentgame.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;} You might want to put that into a class with an overloaded operator(): int & operator( std::size_t row, std::size_t col ) { return ( the_data [ col_size * row + col ] ); } and you could add a const version too: int const & operator( std::size_t row, std::size_t col ) const { return ( the_data [ col_size * row + col ] ); } You also might make the member the_data a std::vector. In that case, you would not even have to take care of your own assignment operator, copy constructor and destructor. E.g:. [code not tested/compiled] template class array2d { std::size_t the_row_size; std::size_t the_col_size; std::vector

 P: n/a red floyd wrote: Kai-Uwe Bux wrote: >John Harrison wrote: >>JoeC wrote:I am crating a new version of my map game and my map will be a 2darray. I had problems trying to create a 2d array dynamically, infact C++ won't let me do it. My question is how to create the size ofarray I need at run time without using too much memory or going overthe allotted size if I choose to use this object for a differentgame.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;} You might want to put that into a class with an overloaded operator(): int & operator( std::size_t row, std::size_t col ) { return ( the_data [ col_size * row + col ] ); }and you could add a const version too: int const & operator( std::size_t row, std::size_t col ) const { return ( the_data [ col_size * row + col ] ); }You also might make the member the_data a std::vector. In that case,you would not even have to take care of your own assignment operator,copy constructor and destructor. E.g:. [code not tested/compiled] template class array2d { std::size_t the_row_size; std::size_t the_col_size; std::vector::size_type size_type; typedef typename std::vector::value_type value_type; typedef typename std::vector::reference reference; typedef typename std::vector::const_reference const_reference; private: size_type the_row_size; size_type the_col_size; std::vector

 P: n/a On Mar 3, 4:53 pm, Doyle Rhynard #include #include //**** Uses **** using std::vector; namespace GPD { template::iterator IterArr; public:// Uses using vector::begin; using vector::end; using vector::size; public:// Constructors ArrayBase(): vector() {} ArrayBase(int Len): vector(Len) {} ArrayBase(const ArrayBase& a): vector(a) {(*this) = a;} public:// Destructor virtual ~ArrayBase() {} public:// Functions int Dim(int N) const {return int(dim[N]);} ArrayBase& operator=(const ArrayBase& a) { vector::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::iterator IterArr; public:// Constructors SubArr(const IterArr IStart, const size_t* ArrSizeDim): sizeDim(ArrSizeDim), iElem(IStart) {} public:// Functions SubArr((iElem+K*sizeDim[0]), (sizeDim+1)); } private:// Variables const size_t* sizeDim; IterArr iElem; }; template::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::iterator IterArr; public:// Uses using vector::begin; using vector::end; using vector::size; using ArrayBase::sizeDim; using ArrayBase::dim; using ArrayBase::iData; public:// Constructors Array(): ArrayBase() {} Array(const Array& a): ArrayBase(a) {} Array(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::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((iData+K*sizeDim[1]), (sizeDim+2)); } }; template: public ArrayBase() {} Array(size_t Len): ArrayBase(Len) {} Array(const ArrayBase& a): ArrayBase(a) {} }; } #endif //======================== Test Program =============================== //**** Includes**** #include "Array.h" #include //**** Uses **** using std::cout; using std::endl; using GPD::Array; int main() { cout << "Start Array Test: " << endl; Array

### This discussion thread is closed

Replies have been disabled for this discussion.