2015-10-16 2 views
2

предположим, что мы имеем класс, как это:Реализация дорогой с ++ итератора

#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); 
} 

EDIT: итератор Неконстантный итератор. В этом примере очень просто, и это не очевидно.

Когда мы делаем первый цикл, новый итератор конца построен для каждой итерации цикла.

Если мы назначим класс из end() переменной (например, memoize), такой проблемы нет.

C++ 11, возможно, делает то же самое.

Наконец, end() может возвращать ссылку, но код намного сложнее и, вероятно, будет создавать проблемы в будущем.

Что такое правильный способ реализации дорогостоящего итератора?

+1

Если вы не модифицируете контейнер, вы можете вызвать 'end()' только один раз перед входом в цикл. См. Также [Sutter] (http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/) –

+0

Да, это константный итератор, я отредактирую вопрос. – Nick

+0

Устойчивость итератора мало что может сделать, если вы измените контейнер (а не содержимое контейнера) – Yakk

ответ

3

См. GotW Herb Sutter на temporary objects. Он предлагает вам позвонить end() только один раз перед входом в цикл, избегая вызова end() для каждой итерации.

Однако он предлагает измерить, является ли временное создание итератора узким местом производительности (например, оно может быть очень быстрым или даже оптимизировано компилятором), чтобы избежать преждевременной оптимизации.

Определение: Преждевременная оптимизация когда вы делаете код более сложным во имя эффективности без данных, что это на самом деле необходимо.

Смежные вопросы