2015-10-16 41 views
2

假設我們有類是這樣的:實施昂貴的C++迭代器

#include <cstdio> 

struct A{ 
    struct it{ 
     it(int i) : i(i){ 
      printf("c-tor %d\n", i); 
     } 

     it &operator++(){ 
      i++; 
      return *this; 
     } 

     int operator*(){ 
      return i; 
     } 

     bool operator!=(const it &ot){ 
      return i != ot.i; 
     } 

     int i; 
    }; 

    it begin() const{ 
     return it(0); 
    } 

    it end() const{ 
     return it(10); 
    } 

    it end_it = it(10); 

    const it &xend() const{ 
     return end_it; 
    } 

}; 

int main(){ 
    A a; 

    printf("for\n"); 
    for(A::it i = a.begin(); i != a.end(); ++i) 
     printf("%d\n", *i); 


    printf("c++11 for\n"); 
    for(int j : a) 
     printf("%d\n", j); 


    printf("memoize\n"); 
    A::it my_end = a.end(); 

    for(A::it i = a.begin(); i != my_end; ++i) 
     printf("%d\n", *i); 


    printf("ref\n"); 
    for(A::it i = a.begin(); i != a.xend(); ++i) 
     printf("%d\n", *i); 
} 

編輯:迭代器是常量迭代。在這個例子中非常簡單,這並不明顯。

當我們首先進行循環時,爲每個循環迭代構造新的結束迭代器。

如果我們將end()中的類賦值給一個變量(例如memoize),則不存在這樣的問題。

C++ 11可能做的完全一樣。

最後,end()可能會返回引用,但代碼要複雜得多,並且可能會在未來出現問題。

實現昂貴的迭代器的正確方法是什麼?

+1

如果你不修改容器,你可能只想在進入循環之前調用'end()'一次。另請參閱[Sutter](http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/) –

+0

是的,這是常量迭代器,我將編輯該問題。 – Nick

+0

如果修改了容器(而不是容器的內容) – Yakk

回答

3

temporary objects看見草本薩特的GotW。他建議您在進入循環之前只能撥打end()一次,避免每次迭代都要撥打end()

不過,他認爲測量迭代器臨時創建是否是一個性能瓶頸(它可能是非常快的,甚至由編譯器優化,例如),以避免過早優化

定義過早的優化是當你在效率的名義代碼更復雜的沒有數據,它的實際需要。