C++ list(STL list)存取(獲取)元素方法詳解

2020-07-16 10:04:28
list 的成員函數 front() 和 back(),可以各自返回第一個和最後一個元素的參照。在空 list 中呼叫它們中的任意一個,結果是未知的,因此不要這樣使用。可以通過疊代器的自增或自減來存取 list 的內部元素。

正如我們所了解的那樣,begin() 和 end() 分別返回的是指向第一個和最後一個元素下一個位置的雙向疊代器。rbegin() 和 rend() 函數返回的雙向疊代器,可以讓我們逆序遍歷元素。因為可以對 list 使用基於範圍的迴圈,所以當我們想要處理所有元素時,可以不使用疊代器:
std::list<std::string> names {"Jane","Jim", "Jules", "Janet"};
names.emplace_back("Ann");
std::string name("Alan");
names.emplace_back(std::move(name)); names.emplace_front("Hugo");
names.emplace(++begin(names), "Hannah");
for(const auto& name : names)
    std::cout << name << std::endl;
迴圈變數 name 是依次指向每個 list 元素的參照,使得迴圈能夠逐行輸出各個字串。下面通過一個練習檢驗一下前面學到的知識。這個練習讀取通過鍵盤輸入的讀語並將它們儲存到一個 list 容器中:
// Working with a list
#include <iostream>
#include <list>
#include <string>
#include <functional>

using std::list;
using std::string;

// List a range of elements
template<typename Iter>
void list_elements(Iter begin, Iter end)
{
    while (begin != end)
        std::cout << *begin++ << std::endl;
}

int main()
{
    std::list<string> proverbs;

    // Read the proverbs
    std::cout << "Enter a few proverbs and enter an empty line to end:" << std::endl;
    string proverb;
    while (getline(std::cin, proverb, 'n'), !proverb.empty())
        proverbs.push_front(proverb);

    std::cout << "Go on, just one more:" << std::endl;
    getline(std::cin, proverb, 'n');
    proverbs.emplace_back(proverb);

    std::cout << "The elements in the list in reverse order are:" << std::endl;
    list_elements(std::rbegin(proverbs), std::rend(proverbs));

    proverbs.sort(); // Sort the proverbs in ascending sequence
    std::cout << "nYour proverbs in ascending sequence are:" << std::endl;
    list_elements(std::begin(proverbs), std::end(proverbs));

    proverbs.sort(std::greater<>()); // Sort the proverbs in descending sequence
    std::cout << "nYour proverbs in descending sequence:" << std::endl;
    list_elements(std::begin(proverbs), std::end(proverbs));
}
執行結果為:

Enter a few proverbs and enter an empty line to end: A nod is a good as a wink to a blind horse.
Many a mickle makes a muckle.
A wise man stands on the hole in his carpet.
Least said, soonest mended.

Go on, just one more:
A rolling stone gathers no moss.
The elements in the list in reverse order are:
A rolling stone gathers no moss.
A nod is a good as a wink to a blind horse.
Many a mickle makes a muckle.
A wise man stands on the hole in his carpet.
Least said, soonest mended.

Your proverbs in ascending sequence are:
A nod is a good as a wink to a blind horse.
A rolling stone gathers no moss.
A wise man stands on the hole in his carpet.
Least said, soonest mended.
Many a mickle makes a muckle.

Your proverbs in descending sequence:
Many a mickle makes a muckle.
Least said, soonest mended.
A wise man stands on the hole in his carpet.
A rolling stone gathers no moss.
A nod is a good as a wink to a blind horse.

因為輸入的一系列諺語中包含空格,所以可以使用 getline() 函數來輸入。每個諺語都是單行讀入,然後通過呼叫 push_front() 函數,將它們作為新的 list 元素新增到 proverbs 容器中。這裡,為了練習使用 emplace_back(),額外新增了一個諺語。由定義在 main() 前面的函數模板 list_dements() 產生輸出結果。這個函數模板可以輸出任意型別的支援流插入操作的元素,只要元素的容器提供輸出疊代器。上面的程式碼演示了如何將這個函數模板與前向疊代器和反向疊代器一起使用。

第一次呼叫 proverbs 的成員函數 sort() 時,沒有提供引數,因此元素被預設排成升序。第二次呼叫時,提供了一個 greater 斷言作為引數;這個模板和其他幾個會在後面遇到的標準斷言模板都定義在標頭檔案 functional 中。表示式 greater<>() 定義了一個函數物件,這個函數物件可以用 opemtor>() 來比較物件,推導模板引數型別。結果,list 中的元素變成了降序排列。還有其他一些物件,它們也定義了一些 sort() 會經常用到的斷言,包括 greater_equal<>()、less<>() 和 less_equal<>()。從名稱就可以看出它們是如何進行比較的。從這個範例的輸入來看,一切都很符合我們的預期。