Re: Dynamic array advice.
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 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;}
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<int>. 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 <typename T>
class array2d {
std::size_t the_row_size;
std::size_t the_col_size;
std::vector<T> the_data;
public:
array2d ( std::size_t r, std::size_t c, T const & val = T() )
: the_row_size ( r )
, the_col_size ( c )
, the_data ( the_row_size * the_col_size, val )
{}
T & operator( std::size_t row, std::size_t col ) {
return ( the_data [ the_col_size * row + col ] );
}
T const & operator( std::size_t row, std::size_t col ) const {
return ( the_data [ the_col_size * row + col ] );
}
std::size_t row_size ( void ) const {
return ( the_row_size );
}
std::size_t col_size ( void ) const {
return ( the_col_size );
}
};
Kai, you missed a pair of parens on both.
T& operator()( std::size_t row, std::size_t col );
T const & operator()( std::size_t row, std::size_t col ) const;
Oops, thanks.
I also missed the asserts that should be there:
T & operator() ( std::size_t row, std::size_t col ) {
assert( row < row_size() );
assert( col < col_size() );
return ( the_data [ the_col_size * row + col ] );
}
T const & operator() ( std::size_t row, std::size_t col ) const {
assert( row < row_size() );
assert( col < col_size() );
return ( the_data [ the_col_size * row + col ] );
}
And, of course, there should be some typedefs like value_type, reference,
const_reference, size_type. So what about:
struct array2d {
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::value_type value_type;
typedef typename std::vector<T>::reference reference;
typedef typename std::vector<T>::const_reference const_reference;
private:
size_type the_row_size;
size_type the_col_size;
std::vector<T> the_data;
size_type pos ( size_type row, size_type col ) {
assert( row < row_size() );
assert( col < col_size() );
return ( the_col_size * row + col );
}
public:
array2d ( size_type r, size_type c, const_reference val = T() )
: the_row_size ( r )
, the_col_size ( c )
, the_data ( the_row_size * the_col_size, val )
{
assert( the_row_size < size_type(-1) / the_col_size );
}
reference operator() ( size_type row, size_type col ) {
return ( the_data [ pos( row, col ) ] );
}
const_reference operator() ( size_type row, size_type col ) const {
return ( the_data [ pos( row, col ) ] );
}
size_type row_size ( void ) const {
return ( the_row_size );
}
size_type col_size ( void ) const {
return ( the_col_size );
}
};
The assert in the constructor is a little too strict.
Best
Kai-Uwe Bux