在下面的例子中我应该期望values.size()
每次循环都会调用它吗?在这种情况下,引入临时vectorSize
变量可能是有意义的.或者现代编译器是否能够通过识别向量大小无法改变来优化调用.
double sumVector(const std::vector& values) { double sum = 0.0; for (size_t ii = 0; ii < values.size(); ++ii) { sum += values.at(ii); } }
请注意,我不关心是否有更有效的方法来对向量的内容求和,这个问题只是在for构造中使用size().
这是一种方法,它使显式 - size()只被调用一次.
for (size_t ii = 0, count = values.size(); ii < count; ++ii)
编辑:我被要求实际回答这个问题,所以这是我最好的镜头.
编译器通常不会优化函数调用,因为它不知道它是否会从一次调用获得不同的返回值.如果循环内部的操作无法预测副作用,它也不会优化.内联函数可能会有所不同,但没有任何保证.局部变量更易于编译器优化.
有些人会称之为过早优化,我同意在很少的情况下你会注意到速度差异.但是,如果它不会使代码更难理解,为什么不把它视为最佳实践并继续使用呢?这肯定不会伤害.
PS我在仔细阅读Benoit的答案之前写过这篇文章,我相信我们完全同意了.
这完全取决于向量的大小实现是什么,编译器的积极程度以及它是否监听/使用内联指令.
我会更加防守并介绍临时性,因为你对编译器的效率没有任何保证.
当然,如果这个例程被调用一次或两次并且向量很小,那实际上并不重要.
如果它会被调用数千次,那么我会使用临时的.
有些人可能会称之为过早优化,但我倾向于不同意这种评估.
在尝试优化代码时,您不会在性能名称上投入时间或混淆代码.
我很难考虑什么是重构才能成为优化.但最后,这就是"你说番茄,我说番茄"......
从'for'构造中的size()开始,直到您需要优化速度.
如果它太慢,请寻找使其更快的方法,例如使用临时变量来保存大小的结果.
无论优化设置如何,将.size()调用放在第二个表达式中最多只能在 for循环之前概述.size()调用.那是:
size_t size = values.size(); for (size_t ii = 0; ii < size; ++ii) { sum += values.at(ii) }
总是表现得至少和以下一样好,如果不是更好:
for (size_t ii = 0; ii < values.size(); ++ii) { sum += values.at(ii); }
在实践中,它可能无关紧要,因为概述.size()调用是一种常见的编译器优化.但是,我发现第二个版本更容易阅读.
不过我发现这更容易:
double sum = std::accumulate(values.begin(), values.end(), 0);