C++ 对for构造中的第二个表达式使用size()是否总是错误的?
在下面的示例中,我是否应该期望在循环中每次都调用C++ 对for构造中的第二个表达式使用size()是否总是错误的?,c++,C++,在下面的示例中,我是否应该期望在循环中每次都调用values.size()?在这种情况下,引入一个临时的vectorSize变量可能是有意义的。或者,现代编译器应该能够通过识别向量大小不能改变来优化调用 double sumVector(const std::vector<double>& values) { double sum = 0.0; for (size_t ii = 0; ii < values.size(); ++ii) {
values.size()
?在这种情况下,引入一个临时的vectorSize
变量可能是有意义的。或者,现代编译器应该能够通过识别向量大小不能改变来优化调用
double sumVector(const std::vector<double>& values) {
double sum = 0.0;
for (size_t ii = 0; ii < values.size(); ++ii) {
sum += values.at(ii);
}
}
double-sumVector(常量标准::向量和值){
双和=0.0;
对于(size_t ii=0;ii
请注意,我不关心是否有更有效的方法对向量的内容求和,这个问题只是关于在for构造中使用size()。这一切都取决于向量的size实现是什么,编译器的攻击性有多大,以及它是否侦听/使用内联指令 我会更具防御性,并引入临时代码,因为您无法保证编译器的效率 当然,如果这个例程被调用一次或两次,并且向量很小,这真的不重要 如果它会被调用数千次,那么我会使用临时的 有些人可能会说这是过早的优化,但我倾向于不同意这种评估。
当您试图优化代码时,您并不是在以性能为名而投入时间或混淆代码
我很难将重构理解为优化。但最后,这是按照“你说西红柿,我说西红柿”的思路进行的。我同意贝诺特的观点。引入一个新变量,特别是int甚至short,会比每次调用它有更大的好处
如果循环变得足够大,可能会影响性能,那么就不必担心了。编译器应该内联std::vector中的size方法,这意味着对size()的每次调用都会被其实际主体所取代(有关内联的更多信息,请参阅问题)。因为在大多数实现中,size()基本上计算end()和begin()之间的差异(也应该是内联的),所以您不必太担心性能的损失 此外,如果我没记错的话,有些编译器非常“聪明”,能够在for构造的第二部分检测表达式的常量,并生成只对表达式求值一次的代码。从“for”构造中的size()开始,直到需要优化速度为止
for (size_t ii = 0, count = values.size(); ii < count; ++ii)
如果速度太慢,请寻找加快速度的方法,例如使用临时变量保存大小的结果。如果在临时变量中保存向量的大小,则与编译器无关
我的猜测是,大多数编译器都会以某种方式优化代码,即size()只被调用一次。但是使用临时变量可以保证,size()只会被调用一次 值得注意的是,即使你要处理数以百万计的项目,开销也可以忽略不计 在任何情况下,都应该使用迭代器编写,因为访问特定示例可能会有更多开销 编译器真的不可能假设size()不会改变,因为它可以 如果迭代的顺序不重要,那么您可以始终按照稍微更有效的方式编写它
for (int i=v.size()-1; i>=0 ;i--)
{
...
}
编译器不知道.size()的值在调用之间是否发生变化,因此不会进行任何优化。我知道您刚刚询问了.size()的使用,但是您应该使用迭代器
std::vector<double>::const_iterator iter = values.begin();
for(; iter != values.end(); ++iter)
{
// use the iterator here to access the value.
}
std::vector::const_迭代器iter=values.begin();
对于(;iter!=values.end();++iter)
{
//使用此处的迭代器访问该值。
}
在本例中,对.end()的调用类似于使用.size()暴露的问题。如果您知道循环不会在向量中执行任何使迭代器无效的操作,则可以在进入循环之前将迭代器初始化到.end()位置,并将其用作边界。在这种情况下,使用迭代器更干净-在某些情况下甚至更快。只有一个对容器的调用——如果还有向量成员,则获取持有指向向量成员指针的迭代器,否则为null
当然的
可以变成,而
完全不需要临时变量-您甚至可以向sumVector函数传递迭代器,而不是常量引用/值。始终按照您的意思第一次编写代码。如果要在向量上从零迭代到size(),请这样编写。不要将对size()的调用优化为临时变量,除非您已将调用分析为程序中需要优化的瓶颈
很有可能,一个好的编译器将能够优化对size()的调用,特别是在向量声明为常量的情况下。这里有一种方法使其显式-size()只调用一次
for (size_t ii = 0, count = values.size(); ii < count; ++ii)
for(size_t ii=0,count=values.size();ii
编辑:我被要求实际回答这个问题,所以这是我最好的答案
编译器通常不会优化函数调用,因为它不知道从一个调用到下一个调用是否会得到不同的返回值。如果循环中存在无法预测其副作用的操作,它也不会进行优化。内联函数可能会有所不同,但没有什么是可以保证的。编译器更容易优化局部变量
有些人会称之为过早的优化,我同意很少有情况下你会注意到速度的差异。但是,如果它不能使代码更难理解,为什么不把它看作是最佳实践呢?当然不会痛的
另外,在我仔细阅读答案之前,我写了这篇文章,我相信我们完全一致。,
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);
}
double sum = std::accumulate(values.begin(), values.end(), 0);