Вычисление условий цикла

В данном цикле, например:

for(int i=0 ; i < strlen(s) ; i++){
    //do something
}

Рассчитывается ли strlen для каждой итерации цикла? Как языки C и C++ справляются с этим? Если этот вызов функции будет выполняться для каждой итерации, и мы заранее знаем, что результат функции будет постоянным, будет ли эффективнее хранить это значение в переменной? например.:

int length = strlen(s);
for(int i=0 ; i< length ; i++){
    //do something
}

3 ответа

Решение

Даstrlen(s) будет оцениваться на каждой итерации.

Если вы не будете изменять строку в цикле, лучше (быстрее) сохранить значение и затем включить его в цикл for.

Самый быстрый способ сделать это:

for(int i=0, length = strlen(s) ; i< length ; i++){
    //do something
}

Рассчитывается ли strlen для каждой итерации цикла?

Да.

более эффективно хранить это значение в переменной?

Да. Вызов функции на каждой итерации и ее обслуживание стека приводит к дополнительным издержкам.

В C++ 11:

template<class T>
struct array_view {
  T*b=nullptr;
  T*e=nullptr;
  T*begin()const{return b;}
  T*end()const{return e;}
  std::size_t size()const{return e-b;}
  bool empty()const{return size()==0;}
  T&operator[](std::size_t i)const{return b[i];}
};

это простой маленький класс. Некоторые помощники, чтобы сделать это:

template<class T>
array_view<T> view(T* b,T* e){return {b,e};}
template<class T>
array_view<T> view(T* b,std::size_t l){return {b,b+l};}
template<class T, unsigned N>
array_view<T> view(T(&a)[N]){return view(&a[0],N};}
template<class T, unsigned N>
array_view<T> view(std::array<T,N>& a){return view(&a[0],N};}
template<class T, unsigned N>
array_view<const T> view(std::array<T,N>const& a){return view(&a[0],N};}
template<class T, class...Xs>
array_view<T> view(std::vector<T,Xs...>& v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<const T> view(std::basic_string<T,Xs...>const & v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<T> view(std::vector<T,Xs...>& v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<const T> view(std::basic_string<T,Xs...>const & v){return view(v.data(),v.size()};}

и наконец:

array_view<char> view(char*str){return view(str, strlen(str));}
array_view<char const> view(char const*str){return view(str, strlen(str));}

Теперь мы можем сделать это:

for(char& c:view(str)){
  // code
}

и получить индекс через &c-str если нам это нужно.

Есть еще один более эффективный подход: используйте Sentinals и указатель на индекс, чтобы избежать вычисления длины до достижения конца.

Другие вопросы по тегам