C++标准库提供了string、array、和vector,他们是一维数组,另有个组间valvarry可以实现多维的数值数组,但他不是容器,而且设计存在一些问题。多维数组虽然实际应用中没有一维数组那么普遍,但也是很有用的。在C++中除了原始数组,只能用vector<vector<T>>来代替了,虽然可用,但不太方便。
multi—array库解决了这个问题,它是一个多维容器,高效地实现了STL风格的多维数组,比使用原始多维数组或者vector of vector更好。
类摘要
multi_array很像标准容器,具有标准容器的大部分接口,它的类摘要如下:
template <typename Valuetype, std ::size_t NumDims>
class multi_array
{
public :
template <std ::size_t Dims> struct subarray;
template <std ::size_t Dims> struct const_subarray;
template <std ::size_t Dims> struct array_view;
template <std ::size_t Dims> struct const_array_view;
multi_array();
explicit multi_array(const ExtentList& size, const storage_order_type& store = c_storage_order());
explicit multi_array(const extents_tuple& ranges, const storage_order_type& store = c_storage_order());
iterator begin();
iterator end();
size_type size()const ;
size_type num_elements()const ;
size_type num_dimensions()const ;
reference operator [](index i);
element& operator ()(const IndexList& indices);
array_view<Dims>::type operator [](const indices_tuple& r);
const_array_view<Dims>::type operator [](const indices_tuple& r)const ;
element* data();
element* origin();
const element* origin()const ;
const size_type* shape()const ;
const index* strides()const ;
const index* index_bases()const ;
const storage_order_tpye& storage_order()const ;
bool operator ==(const multi_array& rhs);
void reshape(const SizeList& sizes);
void assign(InputIterator begin, InputIterator end);
void reindex(const BaseList& values);
void reindex(index value);
multi_array& resize(const extentList& extents);
multi_array& resize(extents_tuple& extents);
};
multi_array 是递归定义的,它的每个维度都是一个multi_array,最底层的则是一个一维的multi—array,因此multi-array是组个模式的一个具体应用
用法
multi_array<int, 3> ma;
定义了一个三维数组ma,相当于int ma[x][y][z].
但仅仅指定了维数还是不够,多维数组还需要指定维度的具体值。
multi—array为了完成这个任务特意提供了extent—gen类和预定义的一个实例boost::extents,它重载了operator[],用起来就像一个原始多维数组,例如:
multi_array<int, 3> ma(extents[2][3][4]);
多维数组的总维度可以用成员函数num_dimensions()获得,它的返回值就是模板参数中的NumDims. 函数shape()返回一个常量指针(数组),里面有NumDims个元素,表明了具体各个维度的值。
multi_array<int , 3 > ma(extents[2 ][3 ][4 ]);
auto shape = ma.shape();
for (size_t i = 0 ; i < ma.num_dimensions(); ++i)
{
cout << shape[i] << "," ;
}
cout << endl << ma.num_elements() << endl;
for (int i = 0 , v = 0 ; i < 2 ; ++i)
for (int j = 0 ; j < 3 ;++j)
for (int k = 0 ;k < 4 ;++k)
{
ma[i][j][k] = v++;
}
for (int i = 0 ; i < 2 ; ++i)
{
for (int j = 0 ; j < 3 ;++j)
{
for (int k = 0 ;k < 4 ;++k)
{
cout << ma[i][j][k] << "," ;
}
cout << endl;
}
cout << endl;
}
std ::array <size_t, 3> idx = {0 ,1 ,2 };
ma(idx) = 10 ;
cout << ma(idx) << endl;
改变形状和大小
multi—array可以在运行时使用成员函数reshape()改变多维数组的形状,即变动各维度的大小,但总维度和元素数量保持不变,变动前的维度乘积与变动后的维度乘积必须相等
multi_array<int , 3 > ma(extents[2 ][3 ][4 ]);
assert(ma.shape()[0 ] == 2 );
std ::array <std ::size_t, 3> arr = {4 ,3 ,2 };
ma.reshape(arr);
assert(ma.shape()[0 ] == 4 );
ma.resize(extents[2 ][9 ][9 ]);
assert(ma.num_elements() == 2 *9 *9 );
assert(ma.shape()[1 ] == 9 );
创建子视图
多维数组的操作是比较复杂的,multi_array库允许用户为多维数组创建一个只查看其中一部分数据的子视图(view),子视图即可以与原始数组拥有相同的维数,也可以少于原来的维数。
typedef multi_array<int , 2 > ma_type;
multi_array<int , 2 > ma(extents[3 ][4 ]) ;
typedef ma_type::index_range range;
auto view = ma[indices[range(0 ,2 )][range(0 ,2 )] ];
cout << view.num_elements() << endl;
for (int i = 0 ; i < 2 ; ++i)
{
for (int j = 0 ; j < 2 ;++j)
{
cout << view[i][j] << "," ;
}
cout << endl;
}
cout << *view.shape() << endl;