【问题标题】:Computation of loop conditions [duplicate]循环条件的计算[重复]
【发布时间】:2014-11-08 02:55:45
【问题描述】:

在给定的循环中,例如:

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

是否为循环的每次迭代计算 strlen(s)? C 和 C++ 语言如何处理这个问题?如果每次迭代都要调用这个函数,并且我们事先知道函数的结果是常量,那么将这个值存储在变量中是否更有效?例如:

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

【问题讨论】:

  • 是的。确实如此。是的。效率更高。
  • 另外,请注意许多编译器(包括 gcc)可以通过缓存 strlen 的结果来优化代码。但是,依赖它并不是一个好习惯。
  • 如果“函数的结果将是常量”是因为您在常量字符串上运行此循环,您可以省略整个 strlen 并将其替换为常量值。 (只是指出“这取决于”......)
  • @Jongware 一些编译器优化 strlen 的文字。

标签: c++ c design-principles


【解决方案1】:

,每次迭代都会评估strlen(s)

如果您不会在循环中更改字符串,最好(更快)将值存储在其中,然后将其包含在 for 循环中。

最快的方法是:

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

【讨论】:

  • "Fastest" ...如果您检查终止的 0,则根本不需要 strlen。差别有多大? strlen 对每个字符检查一次,因此如果您自己执行,则结果相同 - 除了函数调用。
  • @Jongware 只计算一次 strlen 比在每次迭代中计算它更快,这就是我的意思。
【解决方案2】:

是否为循环的每次迭代计算 strlen(s)?

是的。

将此值存储在变量中是否更有效?

是的。在每次迭代中调用一个函数及其堆栈维护会导致一些额外的开销。

【讨论】:

    【解决方案3】:

    在 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
    }
    

    如果需要,可以通过&amp;c-str 获取索引。

    还有一种更有效的方法:使用哨兵和索引指针来避免在到达末尾之前计算长度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 2022-07-06
      • 1970-01-01
      相关资源
      最近更新 更多