1. 程式人生 > >[C++]高效使用迭代器的一些建議

[C++]高效使用迭代器的一些建議

迭代器

本文介紹四種迭代器的使用細節,已經相互轉換的方法,從而提高對迭代的理解和使用。

1. iterator優於const_iterator, const_reverse_iterator, reverse_iterator

iterator幾乎可以適用於所有需要迭代器為引數的函式呼叫。但其他的三種迭代卻不一定。

以下這張圖可以清晰地表明不同迭代器之間的轉換關係。

iterato

我們需要知道的是,有些版本的insert和erase是沒有給出const_iterator的過載版本的,所以如果要在相應位置做操作就必須把他們轉換為iterator才能進行。請注意,不要考慮強制型別轉換,這總是不太好的選擇。後面我們將給出轉換的方法。

2. const_iterator轉換為iterator

之前提到,不要考慮強制型別轉換,是因為這兩個型別是完全不同的型別!(對vector和string可能不適用)所以把兩個完全不同的型別相互轉換是非常沒有道理的。

(在vector和string裡,迭代器會被實現為T* 和 const T*,他們之間是可以進行隱式型別轉換的。)

所以,我們希望得到一種更加普遍可用的方法。

這裡我們需要使用兩個成員函式來解決這個問題。

#include <iostream>
#include <fstream>
#include <deque>
using
namespace std; int main() { typedef deque<int> intDeq; typedef intDeq::iterator iter; typedef intDeq::const_iterator citer; intDeq d; citer ci; iter i(d.begin()); advance(i, distance<citer>(i, ci)); return 0; }

這裡需要注意的是不能直接呼叫distance函式。正如我們前面說的,iterator和const_iterator是兩個不一樣的型別,所以必須給出確定的型別來做比較。

效率上來說,這種方法對於隨機訪問的容器是常數時間操作,對於雙向迭代器來說是線性時間操作。所以效率上來說是不太好的。

3. 正確理解reverse_iterator的base函式

base函式並不是真正的把reverse_iterator轉換iterator, 其中還有一個偏移量的問題。

2

這是base呼叫的偏移量。

因為reverse本來就是從右往左遍歷,所以插入的操作理所應當在iter的右邊,所以insert操作和我們預想的結果是一樣的。

但是對於erase則不是這樣的。因為base會自動往右移一個偏移量,所以我們需要修正這個編譯量,例如,而這很簡單。

    v_i.erase((++iter).base());

4. istreambuf_iterator來作為字元的輸入

除了傳統的使用檔案操作的方法,我們還可以使用迭代器來實現讀取檔案內容。

通過設定dataFile.unsetf(ios::skipws);,我們可以實現忽略空格的輸入。

#include <iostream>
#include <fstream>
using namespace std;
int main() {
    fstream dataFile("data.txt");
    string str((istream_iterator<char>(dataFile)), istream_iterator<char>());
    dataFile.unsetf(ios::skipws);
    copy(str.begin(), str.end(), ostream_iterator<char>(cout));
    return 0;
}

但更簡單的說法是:

#include <iostream>
#include <fstream>
using namespace std;
int main() {
    fstream dataFile("data.txt");
    string str((istreambuf_iterator<char>(dataFile)), istreambuf_iterator<char>());
    copy(str.begin(), str.end(), ostream_iterator<char>(cout));
    return 0;
}