2015-10-16 68 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()

不过,他认为测量迭代器临时创建是否是一个性能瓶颈(它可能是非常快的,甚至由编译器优化,例如),以避免过早优化

定义过早的优化是当你在效率的名义代码更复杂的没有数据,它的实际需要。