boost之array,效率与优雅之正交点

简介:

    如果你是STL的惯用者,且对效率持有莫大的兴趣,你可能会对原生数组而不能优雅的与 STL 算法结合而感到不满和懊恼,你充其量可以这样使用:


int nArray [ 4 ] =  { 1, 2, 3, 4 };
const  int Len =  sizeof ( nArray  ) /  sizeof (  int  );
int nCount = std:: count ( nArray, nArray + Len,  3  );
 


   然而你不肯运用其他如 swap 等算法,数组是一个小型集合, 不能直接赋值。可能在模板中你更渴望有直接赋值的要求:


int nArray [ 4 ] =  { 1, 2, 3, 4 };
int nArray2 [ 4 ] = nArray;         // 这种优雅的语法实在比 memcpy 等更具有观赏性
std:: swap ( nArray, nArray2  );    // 适应这种算法也更通用
 


   幸而,boost提供了这样一个物件: array, 说到底,array 只是原生数组的浅薄包装而已,你甚至可以像原生数组那样直接以大括号形式的赋值方式赋值:


array <int,  2> array =  { { 1, 2 } };
array <int,  2> array =  { 1, 2 };    // 显然大部分编译器已经支持一个大括号的初始化了
 

   这种赋值方式的技术要求是:
         1. 不允许有用户定义的构造函数 ( 可以有析构  )
         2. 不允许有  private 和  protected 的数据成员  ( 可以有  static 成员  )
         3. 不允许有 父类
         4. 无虚函数
   从 C++ 对象模型角度来说,其结构在内存中是连续的一段,没有额外的其他东西如虚表指针.

   下面是其简单定义:
 

    template<class T, std:: size_t N>
     class array  {
       public:
        T elems [N ];     // 被包装之原生数组

       public:
         // 类型定义
         typedef T              value_type;
         typedef T*             iterator;
         typedef  const T*       const_iterator;
         typedef T&             reference;
         typedef  const T&       const_reference;
         typedef std:: size_t    size_type;
         typedef std:: ptrdiff_t difference_type;

         // 迭代器支持
        iterator begin ( )  {  return elems;  }
        iterator end ( )  {  return elems+N;  }

         // 反向迭代器支持
         typedef std:: reverse_iterator<iterator> reverse_iterator;
         typedef std:: reverse_iterator<const_iterator> const_reverse_iterator;

        reverse_iterator rbegin ( )  {  return reverse_iterator (end ( ) )}
        reverse_iterator rend ( )  {  return reverse_iterator (begin ( ) )}

         // 操作符[]
        reference operator [ ] (size_type i ) 
         { 
            BOOST_ASSERT ( i < N &&  "out of range"  )
             return elems [i ];
         }
        
         // 带有检查的 at() 
        reference at (size_type i )  { rangecheck (i )return elems [i ]}
        const_reference at (size_type i )  const  { rangecheck (i )return elems [i ]}
    
         // front() 和 back()
        reference front ( ) 
         { 
             return elems [ 0 ]
         }
        
        reference back ( ) 
         { 
             return elems [N -1 ]
         }
        
         // 大小为常量, 提供了 enum 来支持模板编程
         static size_type size ( )  {  return N;  }
         static  bool empty ( )  {  return  false}
         static size_type max_size ( )  {  return N;  }
         enum  { static_size = N  };

         // swap (线性复杂度)
         void swap  (array<T,N>& y )  {
            std:: swap_ranges (begin ( ),end ( ),y. begin ( ) );
         }

         // direct access to data (read-only)
         const T* data ( )  const  {  return elems;  }
        T* data ( )  {  return elems;  }

         // use array as C array (direct read/write access to data)
        T* c_array ( )  {  return elems;  }

         // 允许类型转换的赋值
         template <typename T2>
        array<T,N>& operator=  ( const array<T2,N>& rhs )  {
            std:: copy (rhs. begin ( ),rhs. end ( ), begin ( ) );
             return * this;
         }

         // 数组填充某一值
         void assign  ( const T& value )
         {
            std:: fill_n (begin ( ),size ( ),value );
         }

         //  检测区间
         static  void rangecheck  (size_type i )  {
             if  (i >= size ( ) )  {
                throw std:: out_of_range ( "array<>: index out of range" );
             }
         }

     };
 


    当 N = 0 时, 像elem[0]这样的语法是错误的,故以偏特化。内部去掉了 T elems[N]; 大部分接口只是为了统一,内部并未实作,顶多是抛出异常。

    另外,一些有用的协助函数,主要是比较函数: ==, <, !=, >, <=, >=. 还有一个全局的swap,内部主要调用array内部的swap实现:

     // swap()
    template<class T, std:: size_t N>
     inline  void swap  (array<T,N>& x, array<T,N>& y )  {
        x. swap (y );
     }

  

瑕疵:

不过,我们只有显示的提供给数组一个大小,不能再像下面一样使用编译器来替我们工作了:

int arr [ ] =  { 1, 2, 3, 4, 5 };

而只有这样:

array<int,  5> arr =  { 1, 2, 3, 4, 5 };

另外,像   char 这样的特殊元素, 我们就不免小心(见下篇)。

不过,比起array之功,这点瑕疵也完全可以忽略。

目录
相关文章
读boost::multi_array有感,多维数组实现(非类型模板,偏特化)
读boost::multi_array有感,多维数组实现(非类型模板,偏特化)
|
存储
1.Boost之array
 1.Boost:array,头文件内容 2.boost:array使用案例 #include&lt;boost/array.hpp&gt; //boost所属的头文件 #include &lt;iostream&gt; #include &lt;string&gt;   using namespace std;
1031 0
|
6月前
|
Python
使用array()函数创建数组
使用array()函数创建数组。
133 3
|
1月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
1月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
|
1月前
|
存储 JavaScript 前端开发
JavaScript Array(数组) 对象
JavaScript Array(数组) 对象
27 3
|
1月前
|
数据采集 JavaScript 前端开发
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
|
2月前
|
Go
Golang语言之数组(array)快速入门篇
这篇文章是关于Go语言中数组的详细教程,包括数组的定义、遍历、注意事项、多维数组的使用以及相关练习题。
35 5
|
3月前
|
Python
PyCharm View as Array 查看数组
PyCharm View as Array 查看数组
92 1
|
4月前
|
索引