STL源码阅读(九)

来源:互联网 发布:linux下oracle无法启动 编辑:程序博客网 时间:2024/04/27 21:57

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;}

参考资料

  1. sgi STL
  2. cppreference.com
0 0
原创粉丝点击