C++ deque修改(替換、更改)元素詳解

2020-07-16 10:04:27
deque 的成員函數 assign() 可以替換現有的所有元素。它有三個重版版本;替換的新內容可以是由初始化列表指定的元素,也可以是由疊代器指定的一段元素,或是一個特定物件的多個副本。

這裡展示了如何使用初始化列表來替換 deque 容器中的內容:
std::deque<std::string> words {"one", "two", "three", "four"};
auto init_list = {std::string{"seven"}, std::string{ "eight"}, std::string{"nine"}};
words.assign(init_list);
最後一條語句用 init_list 中的 string 物件替換掉了 words 中的元素。注意,這裡不能直接把字元放入初始化列表。如果這麼做,init_list 的型別會被推導為 initializer_list<const char*>,然而 assign() 需要的是一個 initializer_list<string> 型別的實參,這樣就無法通過編譯。當然,也可以不單獨定義 init_list,可以在 assign() 的實參中定義初始化列表,例如:
words.assign({"seven”,"eight","nine"});
因為 words 的成員函數 assign() 需要一個 initializer_list<string> 型別的實參,編譯器會用字串列表生成一個這種型別的初始化列表。為了給 deque 容器賦值,需要提供兩個疊代器作為引數:
std::vector<std::string> wordset {"this","that","these","those"};
words.assign(std::begin(wordset)+1, --std::end(wordset));
//Assigns "that" and "these"
assign() 函數只需要輸入疊代器,因此可以使用任何類別的疊代器。最後一種可能是,用重複的物件來替換容器中的內容:
words.assign(8,"eight"); //Assign eight instances of string("eight")
第一個引數指定了替換當前容器內容的第二個引數的個數。vector 也提供了一套同樣的 assign() 函數,所以可以更換一套新的 vector 容器元素。也可以使用賦值操作符來替換賦值運算子左邊的 deque 容器的內容。賦值運算的右運算元必須和左運算元是相同型別,也可以是一個初始化列表。vector 容器同樣也支援這些操作。下面是一個為 deque 替換一套新元素的範例:
std::deque<std::string> words {"one","two","three", "four"};
std::deque<std::string> other_words;
other_words = words; // other_words same contents as words
words = {"seven", "eight", "nine"}; // words contents replaced
執行完這些語句後,otlier_words 會包含和 words 相同的元素,words 則包含初始化列表中的那些元素。賦完值後,容器的大小會反映賦值元素的個數。為一個 vector 容器替換一套新的元素(來自於同型別的 vector 容器或初始化列表),它的大小和這套新元素相同。

下面是一個使用 deque 容器的完整範例:
// Using a deque container
#include <iostream> // For standard streams
#include <algorithm> // For copy()
#include <deque> // For deque container
#include <string> // For string classes
#include <iterator> // For front_insert_iterator & stream iterators

using std::string;

int main()
{
    std::deque<string> names;
    std::cout << "Enter first names separated by spaces. Enter Ctrl+Z on a new line to end:n";
    std::copy(std::istream_iterator < string > {std::cin}, std::istream_iterator < string > {}, std::front_inserter(names));
    std::cout << "nIn reverse order, the names you entered are:n";
    std::copy(std::begin(names), std::end(names), std::ostream_iterator < string > {std::cout, "  "});
    std::cout << std::endl;
}
執行結果為:

Enter first names separated by spaces. Enter Ctrl+Z on a new line to end:
Fred Jack Jim George Mary Zor Rosie
^Z

In reverse order, the names you entered are:
Rosie  Zor  Mary  George  Jim  Jack  Fred

該程式讀入幾個任意長度的字串,然後把它們儲存在 names 容器中。copy() 演算法將從 istream_iterator<string> 獲取到的序列,輸入到 names 容器的 front_insert_itemtor 中,這個疊代器是由函數 front_inserter() 返回的。

copy() 的第一個引數是用來輸入的開始疊代器,第二個引數是對應的結束疊代器。當使用鍵盤輸入 Ctrl+Z 時,輸入疊代器會對應為結束疊代器;如果是從檔案流中讀取資料,當讀到 EOF 時,也會產生一個結束疊代器。因為 deque 容器有成員函數 push_front(),可以用來在序列的頭部新增元素,所以我們這裡可以使用 front_insert_iterator; front_insert_iterator 通過呼叫 push_front()在容器中新增元素,因此它適用於有成員函數 push_front() 的任何容器。

輸出也是由 copy() 演算法生成的。前兩個引數是用來指定元素範圍的疊代器,這些元素被複製到第三個引數所指定的位置。因為前兩個引數正好是 deque 容器的開始和結束疊代器,因此會複製 deque 容器的全部元素。目的地是一個接收字串物件的 ostream_iterator,它會將這些字串物件寫入標準輸出流。