在循环条件下重复求值表达式效率低吗?
Is it inefficient to repetitively evaluate expression in loop condition?
作为初学者,我经常看到循环条件包含函数调用和一些计算密集型表达式,如下所示(例如来自c++ primer,循环语句):
for(int *beg = begin(array); beg != end(array); ++beg) ;
我担心的是:由于在每次迭代中检查条件,在条件内计算表达式的代价不是很高吗(这里运行end()
函数)?
首先,这实际上可能不会对性能产生可测量的影响:如果循环体花费数倍的时间(对于普通代码来说很常见),或者循环作为一个整体不是瓶颈,那么对循环条件的任何优化都是浪费的。
第二,end()
的常用实现是内联的完美候选。一旦它被内联,因为end()
必须没有副作用,迭代器结构受制于循环不变代码运动。在这两个转换之后,实际上与"手动优化"的版本没有区别,程序员无需额外的努力。
因为书籍是说教性的,可读性比性能更重要。对于初学者来说,如果不需要弄清楚优化技巧,就更容易掌握算法的原理!
在现实生活中这也是有道理的:end条件往往是复杂的,并且受到每次迭代的影响。因此,使结束条件易于理解并隐藏实现细节更安全,更易于维护。
如果性能真的很重要,首先想想B.Kernighan的声明:"不要为了更快而篡改代码,而是要找到更好的算法"。
对于非常简单的时间临界循环,可能值得关注事实。编写循环的方式很重要。这里有一些在字符串中进行大规模迭代搜索的基准测试:
- 传统迭代器方法每次检查.end(): 14秒
- 在变量中循环开始时缓存.end(): 10秒,提高30% !
- 使用计数器索引,每次检查.size(): 860 ms
- 从结束开始计数到0:670 ms,提高22% !
- 使用指向c_str()的指针,将整个事情减少到…63毫秒!
但是请记住,最好的优化器是你的编译器。在开启优化后,时间分别为1274 ms, 6777 ms, 42 ms, 42 ms和33ms,即从50%到92%的提高!
相关文章:
- (C++)分析树以计算返回错误值的简单算术表达式
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 提升精神:解析布尔表达式并简化为规范范式
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 使用正则表达式regex_search在字符串中查找字符串
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 概念中的cv限定符需要表达式参数列表
- 为什么constexpr的性能比正常表达式差
- 对于结构,表达式必须是可修改的ivalue
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 将fold表达式与std::一起用于两个元组
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 标记 '","' 之前的预期主表达式
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 如何计算具有指定类型的表达式的相对精度和绝对精度
- 为什么当我解模块化时,这个C++代代码"效率较低"?
- 带有用户定义类的c++折叠表达式
- 即使使用调试编译标志,表达式也是"optimized out"
- holeMenuProgram.cpp:38:1 错误:'}'令牌之前的预期主表达式
- 在循环条件下重复求值表达式效率低吗?