2011-08-20 35 views
0

請注意這段代碼不是由我寫的。否則我不會問這個問題。全額抵免Jerry Coffin。無論如何,代碼通過重載std :: iterator <>來生成一系列數字。重載迭代器:C++語義問題

我會先發布代碼,然後我會給我解釋我所看到的。如果一個專家的C++成員可以糾正我,如果我錯了,我將不勝感激。

代碼

static const int N = 10; 
template <class T> 
class sequence : public std::iterator<std::forward_iterator_tag, T> 
{ 
private: 
    T val; 
public: 
    sequence(T init) : val(init) { } 
    T operator *() { return val; } 
    sequence &operator++() { ++val; return *this; } 
    bool operator != (const sequence &other) { return val != other.val; } 
}; 

void foo() 
{ 
    typedef std::vector<int> graph; 
    graph id1(gen_seq(0), gen_seq(N)); 
    display(id1);        /* Not declared */ 
} 

/* displays: 0 1 2 3 4 5 6 7 8 9 */ 

所以在看這個的時候我看到你創建一個包含價值的一類。現在我們將其中兩個傳遞給vector的構造函數,它可以使用兩個迭代器。現在,每次向量的構造函數在「序列」上使用++運算符時,它都會遞增迭代器中的值。從技術上講,你可以這樣寫:

graph id1(gen_seq(0), gen_seq(0)); 

這樣會產生相同的序列是否正確?或者它是檢查以確保0還沒有到達N的!=運算符。對此的任何輸入都會有很大的幫助。我剛剛讀完Stroustrup的C++編程語言第3版,在那裏他談到了迭代器,但是從它們繼承來的並不是一個大話題,而我還沒有完全理解。我會完成他所有的練習,因爲我記得他要求重複迭代器幾次。

+0

這不是重載,它只是繼承。 –

+0

對不起,用錯了名詞。我將編輯我的帖子 –

+1

爲了完整起見,還要注意前向迭代器也必須提供以下操作:默認構造,後綴'++'和等號('==')。所有這三項都可以根據您已經定義的運營商輕鬆定義。 –

回答

5

你不是真的重載一個迭代器;你正在編寫你自己的迭代器,它涉及到一些運算符的重載。

std::vector構造有效看起來是這樣的:

template <typename ForwardIterator> 
vector(ForwardIterator first, ForwardIterator last) 
{ 
    for (ForwardIterator it = first; it != last; ++it) 
     push_back(*it); 
} 

(在現實中,它是比這更復雜,因爲它需要更有效地處理隨機存取的範圍,但對於前進迭代範圍,這是什麼它)

正如你所看到的,構造上執行你的迭代三個操作:它解引用它(*it),它增加它(++it),並執行不等號(it != last)。在這些事情中,它會調用您在自定義迭代器類中定義的相應運算符。

graph id1(gen_seq(0), gen_seq(0));會工作,但它不會給出相同的結果:它會留下id1爲空。根據前幾段的解釋,你明白了爲什麼?

+0

我會補充說,你甚至不必從'iterator'繼承這個工作。 –

+0

右鍵:繼承自'std :: iterator'只是爲你的類提供了所有迭代器都需要的類型定義;你可以自己輕鬆定義它們。你可以看看你的標準庫實現的'std :: iterator'實現,看看它究竟做了什麼。 –

+0

我確實看到了它,並且你的帖子有幫助,因爲for循環永遠不會執行,所以它不起作用!= last會比較我的類中的值。 –

3

graph id1(gen_seq(0), gen_seq(0));會生成零大小的向量。你的第二個解釋使用!=更接近。如果你瞭解矢量ctor代碼,可能會有所幫助。它是這樣的

template <class II> 
vector::vector(II first, II last) 
{ 
    while (first != last) 
    { 
    push_back(*first); 
    ++first; 
    } 
} 

正如你可以看到!=被用來確定何時停止將項目添加到載體。 (由於各種技術和效率的原因,實際的矢量ctor代碼可能比這個複雜得多,但是上面給出了本質,因爲它適用於你的情況)。