用类模拟一个二维数组
想设计一个类来模拟二维数组的行为,求大家给几个思路或代码。 类 二维数组
[解决办法]
内存要连续, 又要支持 xx[2][3] 这种写法的话, 中间需要有个代理类.
[解决办法]
下面的代码中的row_accessor就是代理类,是为了实现ary[i][j]的访问方法。
class double_array_2d
{
public:
//缺省构造函数,空数组
double_array_2d()
: data(0)
, row_count(0)
, col_count(0)
{
}
//构造函数,创建一个crow行ccol列的二维数组
double_array_2d( int crow, int ccol )
: data( new double[ crow * ccol ] )
, row_count( crow )
, col_count( ccol )
{
}
//拷贝构造函数,分配空间并复制数据
double_array_2d ( double_array_2d const & src )
: data( new src.row_count * src.col_count )
, row_count( src.row_count )
, col_count( src.col_count )
{
for( int i = 0; i < row_count * col_count; ++ i )
{
data[i] = src.data[i];
}
}
//析构时释放空间。
~double_array_2d()
{
if( data )
{
delete []data;
}
}
//普通的访问方法,调用者需要保证不越界,调试版本用断言检查
double & at( unsigned int row, unsigned int col )
{
assert( row < row_count && col < col_count );
return data[ row * col_count + col ];
}
//普通的访问方法,常量版本,调用者需要保证不越界,调试版本用断言检查
double at( unsigned int row, unsigned int col )
{
assert( row < row_count && col < col_count );
return data[ row * col_count + col ];
}
//下面实现operator[ ],也可以不实现,只用at进行访问。
//这个类是辅助operator[ ]用的,因为operator[ ]只接收一个参数。
class row_accessor
{
public:
row_accessor( double * data, unsigned int length )
: my_data(data)
, my_length(length)
{
}
double & operator[] ( unsigned int col ) throw()
{
assert( col < my_length );
return data[ col ];
}
double operator[] ( unsigned int col ) const throw()
{
assert( col < my_length );
return data[ col ];
}
};
row_accessor operator[]( int row ) throw()
{
return row_accessor( data[ row ] );
}
const row_accessor operator[]( int row ) const throw()
{
return row_accessor( row );
}
//交换两个数组的数据
//拷贝构造函数和redim通过调用这个方法实现。
//这是除了构造与析构以外,唯一直接改变data、row_count与col_count的成员函数
//其改变也是在两个构造完成的array之间进行交换,并且是长度与指针信息一同交换,
//从而保证内存分配与释放的安全性
void swap( double_array_2d & other ) throw()
{
unsigned int crow = row_count;
unsigned int ccol = col_count;
double * my_data = data;
data = other.data;
row_count = other.row_count;
col_count = other.col_count;
other.data = my_data;
other.row_count = crow;
other.col_count = ccol;
}
//重新分配,可以增加代码以保持数组中的数据,用构造函数+swap实现
void redim( unsigned int crow, unsigned ccol )
{
double_array_2d temp( crow, ccol );
//可以添加代码把data中的数据或一部分数据拷贝到temp中。
//拷贝时要用二重循环,用at或operator[]访问数据
temp.swap( * this );
}
//拷贝赋值操作符,用拷贝构造函数和swap实现
double_array_2d & operator = ( double_array_2d const & other )
{
double_array_2d temp( other );
temp.swap( * this );
}
private:
unsigned int row_count;
unsigned int col_count;
double * data;
private:
//如果不想实现拷贝构造和拷贝赋值,可以用下面的代码禁止拷贝操作
//这时前面的拷贝构造函数和拷贝赋值操作符的定义就不需要了
//double_array_2d ( double_array_2d const & src );
//double_array_2d & operator = ( double_array_2d const & other );
};
template<unsigned int L,typename T>
class array
{
T data[L];
public:
T & operator[] (unsigned int i )
{
return data[i];
}
T const & operator[] ( unsigned int i ) const
{
return data[i];
}
};
和内置的二维数组的内存布局相同,可以当做内置二维数组用。
b) 每个1级指针都分配数据内存,这个不太像,内置二维数组的内存布局;
如果定义一个函数可以用于,内置二维数组的话
一定不能用于这种方式模拟的数组,因为内存不连续。
好处是,可以适应内存碎片比较严重的情况,每次分配的内存要小得多