C
gegen vector< vector< T > > ist nicht unbedingt etwas einzuwenden, solange du nur über Koordinaten navigierst. Eine andere Methode verwendet valarray mit slice - aber auch dafür muss man sich erst etwas einlesen. Eine selbstgeschrieben Klasse tut es auch:
template<typename T, typename A = std::allocator< T > >
class Array2D
{
public:
typedef A allocator_type;
typedef typename allocator_type::value_type value_type;
typedef typename allocator_type::size_type size_type;
typedef typename allocator_type::difference_type difference_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef pointer iterator;
typedef const_pointer const_iterator;
explicit Array2D(size_type x = 0, size_type y = 0, const_reference value = value_type())
: x_( x ), y_( y ), p_( A().allocate( x * y ) )
{
try
{
std::uninitialized_fill( begin(), end(), value );
}
catch ( ... )
{
A().deallocate( begin(), size() );
throw;
}
}
Array2D(const Array2D& other)
: x_( other.x_dim() ), y_( other.y_dim() ), p_( A().allocate( other.size() ) )
{
try
{
std::uninitialized_copy( other.begin(), other.end(), begin() );
}
catch ( ... )
{
A().deallocate( begin(), size() );
throw;
}
}
~Array2D()
{
allocator_type allocator;
for ( iterator p = end(); p != begin(); )
allocator.destroy( --p );
allocator.deallocate( p_, size() );
}
Array2D& operator=(const Array2D& rhs)
{
Array2D( rhs ).swap( *this );
return *this;
}
void swap(Array2D& other)
{
using std::swap;
swap( x_, other.x_ );
swap( y_, other.y_ );
swap( p_, other.p_ );
}
size_type x_dim() const { return x_; }
size_type y_dim() const { return y_; }
size_type size() const { return x_dim() * y_dim(); }
iterator begin() { return p_; }
const_iterator begin() const { return p_; }
iterator end() { return begin() + size(); }
const_iterator end() const { return begin() + size(); }
pointer operator[](size_type x) { return p_ + x * y_dim(); }
const_pointer operator[](size_type x) const { return p_ + x * y_dim(); }
reference operator()(size_type x, size_type y) { return p_[ x * y_dim() + y ]; }
const_reference operator()(size_type x, size_type y) const { return p_[ x * y_dim() + y ]; }
private:
size_type x_;
size_type y_;
pointer p_;
};
template<typename T, typename A>
void swap(Array2D< T, A >& lhs, Array2D< T, A >& rhs)
{
lhs.swap( rhs );
}
hier fehlt ein bisschen Funktionalität (z.B. resize und assign). Zuviel davon rückt das ganze dann allerdings wieder sehr nahe an existierende Varianten (insbesondere valarray) heran, dann lohnt sich eine eigene Klasse schon wieder nicht. Es hängt eben sehr vom Verwendungszweck ab.