C++ array疊代器及用法

2020-07-16 10:04:27

陣列模板定義了成員函數 begin() 和 end(),分別返回指向第一個元素和最後一個元素的下一個位置的隨機存取疊代器。如前面章節所述,隨機存取疊代器具有最多的功能,能使用它進行全部的操作。可以在迴圈中顯式地使用疊代器來設定 height_ins 容器的值:

unsigned int h {min_ht};
auto first = height_ins.begin();
auto last = height_ins.end () ;
while (first != last)
{
    *first++=h;
    h += ht_step;
}
疊代器物件是由 array 物件的成員函數 begin() 和 end() 返回的。使用 auto 時小需要擔心疊代的實際型別,除非你要自己考慮,在本例中它們是 std::array<unsigned int,19>::iterator 型別,這意味著 iterator 型別被定義在 array<T,N> 型別中。可以看出,可以像使用普通指標那樣上使用疊代器物件。在儲存了元素值後,使用字尾 ++ 運算子對 first 進行自增。當 first 等於 end 時,所有的元素都被設完值,迴圈結束。

如前面章節所述,最好用全域性的 begin() 和 end() 函數來從容器中獲取疊代器,因為它們是通用的,first 和 last 可以像下面這樣定義:
auto first = std::begin(height_ins);
auto last = std::end (height_ins);
記住,當迭代器指向容器中的一個特定元素時,它們沒有保留任何關於容器本身的資訊,所以我們無法從疊代器中判斷,它是指向 array 容器還是指向 vector 容器。容器中的一段元素可以由疊代器指定,這讓我們有了對它們使用演算法的可能。

定義在 algorithm 標頭檔案中的 generate() 函數模板,提供了用函數物件計算值、初始化一切元素的可能。我們可以像這樣重寫之前用來初始化 height_ins 容器的程式碼段:
unsigned int height {};
std::generate(std::begin(height_ins), std::end(height_ins),[height, &min_ht, &ht_step]()mutable
{ return height += height == 0 ? min_ht : ht_step; });
為容器元素設定值的語句現在減少到兩條,也不再需要顯式的迴圈語句。第一條語句定義了一個變數用來儲存元素的初始值。genemte() 的前兩個引數分別是開始疊代器和結束疊代器,用來指定需要設定值的元素的範圍。第三個引數是一個 lambda 表示式。lambda 表示式以參照的方式捕獲 min_hi、ht_step。mutable 關鍵使 lambda 表示式能夠更新 height 區域性副本的值,它是以值參照的方式捕獲的。

在 return 語句中,lambda 第一次執行後,height 的區域性副本的值被設為 min_ht。然後,隨著 lambda 的每次呼叫,height 都會增加 ht_step。 在 lambda 表示式中,以值參照的方式捕獲的變數區域性副本的值會被一直儲存,這一機制正好滿足了我們的要求。

假定要用連續的遞增值初始化一個陣列容器,這裡有一個函數模板 iota() 可以做到,它定義在標頭檔案 numeric 中。這裡有一個它的用法範例:
std::array<double, 10> values;
std::iota(std::begin(values), std::end(values),10.0);
    elements to 10.0 to 19.0
前兩個引數是疊代器,用來定義需要設定值的元素的範圍。第三個引數是第一個元素要設定的值,通過遞增運算生成了隨後每一個元素的值。iota()函數的使用並不僅限於數值。元素可以設為任意型別的值,只要這些型別支援 operator++()。

注意,不要忘記演算法是獨立於容器型別的,對於任何具有指定型別疊代器的容器來說,演算法都可以應用到它們的元素上。generate() 和 iota() 函數模板只需要正向疊代器,所以用來指定任何容器的元素範圍的疊代器都能發揮作用。

容器定義了成員函數 cbegin() 和 cend(),它們可以返回 const 疊代器。當只想存取元素時,應該使用 const 疊代器。對於 non-const 疊代器,最好使用全域性的 cbegin 和 cend() 來獲取。全域性函數或成員函數 rbegin() 和 rend() 可以分別得到指向最一個元素和第一個元素前一個位置的反向疊代器。函數 crbegin() 和 crend() 可以返回 const 反向疊代器。我們可以用反向疊代器以逆序方式處理元素。例如:
std::array<double, 5> these {1.0, 2.0, 3.0, 4.0, 5.0};
double sum {};
auto start = std::rbegin(these);
auto finish = std::rend(these);
while(start != finish)
    sum += *(start++};
std::cout << "The sum of elements in reverse order is " << sum << std::endl;
在迴圈中,從最後一個元素幵始,我們計算出了所有元素的和。結束疊代器指向第一個元素之前的位置,所以 sum 加上第一個元素後,迴圈就結朿了。在反向疊代器上使用遞增運算子,會讓疊代器用一種和普通正向疊代器移動方向相反的方式移動。我們也可以使用 for 迴圈:
for (auto iter = std::rbegin (these); iter != std::rend(these); ++iter)
    sum += *iter;
因為陣列容器範例的元素個數固定,所以無法使用插入疊代器。插入疊代器通常用來向容器中新增元素。