STL源码阅读(九)
STL源码阅读(九)(SGI STL v3.3)
limits (<limits>)
提供编译时算术类型变量的属性信息。
valarray (<valarray>)
数值数组类
// valarray的元素选择类
class slice {
...
private:
size_t _M_start; // 起始元素的位置
size_t _M_length; // 元素的个数
size_t _M_stride; // 元素之间的步长
...
}
// slice作为角标号的帮助类
template <class _Tp>
class slice_array {
friend class valarray<_Tp>;
public:
typedef _Tp value_type;
...
slice _M_slice; // 下标
valarray<_Tp>& _M_array; // 数值数组
...
// 定义了=、*=、/=、%=、+=、-=、^=、&=、|=、<<=、>>=,算术、逻辑与移位操作
// 操作都是在指定的角标处的元素上进行运算的,看一小段源码即可明白
void operator=(const valarray<value_type>& __x) const {
size_t __index = _M_slice.start();
for (size_t __i = 0;
__i < _M_slice.size();
++__i, __index += _M_slice.stride()) // 对于赋值数组__x是以1为角标步长的
_M_array[__index] = __x[__i];
}
}
// valarray的元素选择类,可以选择多组(形成多维数组)
class gslice {
private:
size_t _M_start; // 起始元素下标
valarray<size_t> _M_lengths; // 每一维的元素个数
valarray<size_t> _M_strides; // 定义每一维元素之间的步长
...
}
template <class _Tp>
class gslice_array {
friend class valarray<_Tp>;
public:
typedef _Tp value_type;
...
gslice _M_gslice; // 下标
valarray<value_type>& _M_array; // 数值数组
...
}
// 所定义的操作符类似于slice_array,只不过前者是多维的
// 在有效的下标处进行操作
template <class _Tp>
class mask_array {
friend class valarray<_Tp>;
public:
typedef _Tp value_type;
...
valarray<bool> _M_mask;
valarray<_Tp>& _M_array;
...
}
// 在指定的一些下标处进行操作
template <class _Tp>
class indirect_array {
friend class valarray<_Tp>;
public:
typedef _Tp value_type;
...
valarray<size_t> _M_addr;
valarray<_Tp>& _M_array;
...
}
// valarray基类
template <class _Tp>
struct _Valarray_base {
...
_Tp* _M_first; // 指向数组的指针,分配的是一段连续内存
size_t _M_size; // 数组大小
...
// 使用malloc和free来分配、释放内存
}
template <class _Tp>
class valarray : private _Valarray_base<_Tp> {
...
friend class gslice;
public:
typedef _Tp value_type;
// 注意标量赋值是将所有元素赋为同一个值
valarray& operator=(const value_type& __x) {
fill_n(this->_M_first, this->_M_size, __x);
return *this;
}
// 注意resize会先释放原内存,然后再分配__n*sizeof(value_type)
// 大小的内存,并以__x初始化每个元素
void resize(size_t __n, value_type __x = value_type()) {
destroy(this->_M_first, this->_M_first + this->_M_size);
this->_Valarray_base<_Tp>::_M_deallocate();
this->_Valarray_base<_Tp>::_M_allocate(__n);
uninitialized_fill_n(this->_M_first, this->_M_size, __x);
}
...
}
// 注意operator*是按照对应元素相乘的,不是向量乘。其它算术操作同理
template <class _Tp> inline valarray<_Tp> operator*(const valarray<_Tp>& __x,
const valarray<_Tp>& __y) {
typedef typename valarray<_Tp>::_NoInit _NoInit;
valarray<_Tp> __tmp(__x.size(), _NoInit());
for (size_t __i = 0; __i < __x.size(); ++__i)
__tmp[__i] = __x[__i] * __y[__i];
return __tmp;
}
// 返回一个新的数值数组,它的元素是原数组平移n(正值向左,负值向右)后的元素的副本
template <class _Tp>
valarray<_Tp> valarray<_Tp>::shift(int __n) const
{
valarray<_Tp> __tmp(this->size());
if (__n >= 0) {
if (__n < this->size())
copy(this->_M_first + __n, this->_M_first + this->size(),
__tmp._M_first);
}
else {
if (-__n < this->size())
copy(this->_M_first, this->_M_first + this->size() + __n,
__tmp._M_first - __n);
}
return __tmp;
}
// 循环平移数组元素
template <class _Tp>
valarray<_Tp> valarray<_Tp>::cshift(int __m) const
{
valarray<_Tp> __tmp(this->size());
// Reduce __m to an equivalent number in the range [0, size()). We
// have to be careful with negative numbers, since the sign of a % b
// is unspecified when a < 0.
long __n = __m;
if (this->size() < numeric_limits<long>::max())
__n %= long(this->size());
if (__n < 0)
__n += this->size();
copy(this->_M_first, this->_M_first + __n,
__tmp._M_first + (this->size() - __n));
copy(this->_M_first + __n, this->_M_first + this->size(),
__tmp._M_first);
return __tmp;
}