boost庫區間range基本原理及使用實例

由 www.169it.com 蒐集整理html

區間的概念相似於STL中的容器概念。一個區間提供了能夠訪問半開放區間[first,one_past_last)中元素的迭代器,還提供了區間中的元素數量的信息。算法

引入區間概念的目的在於:有不少相似於容器的類型,以及用於這些類型的簡化算法。express

實例代碼:數組

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void  test_range_construct_string()
  {
     typedef  std::string::iterator   iterator;
     typedef  std::string::const_iterator const_iterator;
     typedef  boost::iterator_range<iterator>   irange;
     typedef  boost::iterator_range<const_iterator> cirange;
     std::string       str  =  "hello world" ;
     const  std::string cstr =  "const world" ;
                                                                                                 
     // 1. 基本構建方法
     boost::iterator_range<std::string::iterator> ir(str);
     boost::iterator_range<std::string::const_iterator> cir(str);
     // 2. 利用make_iterator_range(幾種重載函數)
     irange r    = boost::make_iterator_range(str);
     r           = boost::make_iterator_range(str.begin(), str.end());
     cirange r2  = boost::make_iterator_range(cstr);
     r2          = boost::make_iterator_range(cstr.begin(), cstr.end());
     r2          = boost::make_iterator_range(str);
     assert (r == str);
     assert (r.size() == 11);
     irange r3   = boost::make_iterator_range(str, 1, -1);
     assert (boost::as_literal( "ello worl" ) == r3);
     irange r4   = boost::make_iterator_range(r3, -1, 1);     // 這個也能夠理解成複製構造
     assert (str == r4);
     std::cout << r4 << std::endl;
     irange r5 = boost::make_iterator_range(str.begin(), str.begin() + 5);
     assert (r5 == boost::as_literal( "hello" ));
  }

類型變化:函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void  test_range_type()
  {
     using  namespace  boost;
     // 數組
     const  int  SIZE = 9;
     typedef  int  array_t[SIZE];
     const  array_t ca = {1, 2, 3, 4, 5, 6, 7, 8, 10};
     assert ((is_same<range_iterator<array_t>::type,        int *          >::value));
     assert ((is_same<range_value<array_t>::type,              int            >::value));
     assert ((is_same<range_difference<array_t>::type,     std:: ptrdiff_t >::value));
     assert ((is_same<range_size<array_t>::type,           std:: size_t    >::value));
     assert ((is_same<range_const_iterator<array_t>::type,  const  int *    >::value));
     assert (begin(ca) == ca);
     assert (end(ca) == ca + size(ca));
     assert (empty(ca) ==  false );
  }

range-for是C++ 11新增特性,用於循環迭代一個「範圍」,該「範圍」相似於包含有begin()和end()方法的STL序列容器。全部的STL標準容器都適用於該「範圍」,例如vector、string等等。數組也一樣能夠,只要定義了begin()和end()方法的任何「範圍」均可以使用for來循環迭代容器裏面的元素,如istream。oop

語法:spa

1
for  ( range_declaration : range_expression) loop_statement

上述代碼的效果相似於:指針

1
2
3
4
5
6
7
8
9
(__range, __begin and __end are  for  exposition only):
{     auto  && __range = range_expression ; 
for  ( auto  __begin = begin_expr, __end = end_expr;          
__begin != __end; ++__begin) 
{     
range_declaration = *__begin;      
loop_statement    
}
}


迭代器begin_expr和end_expr能夠被定義成以下類型:code

* 若是__range是數組,(__range) 和 (__range + __bound)表示數組的範圍orm

*若是__range是一個類,實現了begin()或end()方法,或者兩個方法都實現了,此時begin_expr就表示 __range.begin(),而 end_expr則表示 __range.end()。

不然begin(__range)和end(__range)將經過基於與std名稱空間關聯的參數依賴查找規則來查找。

若是range_expression返回一個臨時變量,它的生命週期到循環結束,如綁定到右值__range的,但要注意,臨時嵌套在range_expression中的並無延長其生命週期。

如同傳統的for語句,關鍵字break能夠提早結束循環,而continue能夠繼續循環。

example:

1
2
3
4
5
void  f(vector< double >& v)
  {     for  ( auto  x : v)
       cout << x <<  '/n' ;
       for  ( auto & x : v) ++x;     // 經過引用能夠修改v中的值5
  }

for也能夠用於迭代普通的數組,如:

1
2
for  ( const  auto  x : { 1,2,3,5,8,13,21,34 })
cout << x <<  '/n' ;

誤區:

1
2
3
4
5
int * p =  new  int  [2];
p[0] = 1;
p[1] = 2;
for  ( auto  x : p)
cout << x << endl;

編譯器會報錯誤:

錯誤:對‘begin(int*&)’的調用沒有匹配的函數


經過上面對for的介紹能夠知道,for實現的機制就是依賴與容器中的begin()和end()方法。對於普通的數組,編譯器默認已經實現了相似的方法。這裏的p是一個指針,儘管它能夠像數組同樣使用,可是它並無相似與begin()或end()的方法,固然會編譯不經過。

以上內容根據我的理解結合互聯網上相關做者介紹總結,錯誤再所不免。

相關文章
相關標籤/搜索