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;
1077 0
|
5月前
|
测试技术 PHP 开发者
PHP 数组查找:为什么 `isset()` 比 `in_array()` 快得多?
PHP 数组查找:为什么 `isset()` 比 `in_array()` 快得多?
|
9月前
|
人工智能 Java
Java 中数组Array和列表List的转换
本文介绍了数组与列表之间的相互转换方法,主要包括三部分:1)使用`Collections.addAll()`方法将数组转为列表,适用于引用类型,效率较高;2)通过`new ArrayList&lt;&gt;()`构造器结合`Arrays.asList()`实现类似功能;3)利用JDK8的`Stream`流式计算,支持基本数据类型数组的转换。此外,还详细讲解了列表转数组的方法,如借助`Stream`实现不同类型数组间的转换,并附带代码示例与执行结果,帮助读者深入理解两种数据结构的互转技巧。
589 1
Java 中数组Array和列表List的转换
|
12月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
244 67
|
9月前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
供应链 JavaScript 前端开发
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
Web App开发 存储 前端开发
别再用双层遍历循环来做新旧数组对比,寻找新增元素了!使用array.includes和Set来提升代码可读性
这类问题的重点在于能不能突破基础思路,突破基础思路是从程序员入门变成中级甚至高级的第一步,如果所有需求都通过最基础的业务逻辑来做,是得不到成长的。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
数据采集 JavaScript 前端开发
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
用array.filter()来实现数据筛选、数据清洗和链式调用,相对于for循环更加清晰,语义化强,能显著提升代码的可读性和可维护性。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

热门文章

最新文章

  • 1
    Java 中数组Array和列表List的转换
    589
  • 2
    JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
    552
  • 3
    通过array.reduce()实现数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式、聚合统计、处理树结构数据和性能优化,reduce()的使用详解(附实际应用代码)
    1324
  • 4
    通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
    390
  • 5
    通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
    243
  • 6
    多维数组操作,不要再用遍历循环foreach了!来试试数组展平的小妙招!array.flat()用法与array.flatMap() 用法及二者差异详解
    157
  • 7
    别再用双层遍历循环来做新旧数组对比,寻找新增元素了!使用array.includes和Set来提升代码可读性
    181
  • 8
    Array.forEach实战详解:简化循环与增强代码可读性;Array.forEach怎么用;面对大量数据时怎么提高Array.forEach的性能
    126
  • 9
    深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
    441
  • 10
    JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
    823