循环条件的计算

Computation of loop conditions

本文关键字:计算 条件 循环      更新时间:2023-10-16

在给定循环中,例如:

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
}

,将在每次迭代中评估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和指向索引的指针,以避免在到达末尾之前计算长度。