C++ c++;for循环临时变量使用
以下哪项更好?为什么?(特别是c++) aC++ c++;for循环临时变量使用,c++,for-loop,C++,For Loop,以下哪项更好?为什么?(特别是c++) a inti(0),iMax(vec.length())//vec是一个容器,比如std::vector 对于(;i > /P> 令人惊讶的是,有多少C/C++开发人员仍然错误地理解了这一点。示例(b)与示例(a)有不同的含义,编译器必须在编写时对其进行解释 如果(出于我无法想象的虚构原因),我编写了代码来实现这一点: for( int i(0);i < vec.length(); ++i) { if(i%4 == 0) vec
inti(0),iMax(vec.length())//vec是一个容器,比如std::vector
对于(;i
b
for(int i(0);i
我看到了(a)的建议,因为调用了length函数。这让我很烦恼。难道没有任何现代编译器对(b)进行类似于(a)的优化吗?简单的问题:您是否在循环中修改
vec
回答这个问题也会得到你的答案
jrh我喜欢:
for (int i = 0, e = vec.length(); i != e; ++i)
当然,这也适用于迭代器:
for (vector<int>::const_iterator i = v.begin(), e = v.end(); i != e; ++i)
for(vector::const_迭代器i=v.begin(),e=v.end();i!=e;++i)
我喜欢它,因为它既高效(只调用一次
end()
),又相对简洁(只需键入vector::const\u迭代器一次)。编译器很难在知道它是常量的安全知识下调用vec.length()
,除非它是内联的(希望经常如此!)但至少应该在第二个样式“b”中声明i
,即使length
调用需要“手动”从循环中提升出来!为什么这会困扰您?
这两个备选方案并不相同,一个是进行固定次数的迭代,而另一个则取决于循环体
另一种选择是
for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
//loop body
}
for(vector::iterator it=vec.begin();it!=vec.end();it++){
//环体
}
除非需要循环外部的循环变量,否则第二种方法更可取
迭代器实际上会给你带来更好或更好的性能。(在COMP。Lang.c++上有一个比较大的线程。几年前有所调整)。
还有,我会用
int i = 0;
而不是您正在使用的类似构造函数的语法。虽然有效,但它不是惯用语法。有些不相关:
警告:有符号整数和无符号整数之间的比较
数组和向量索引的正确类型是size\u t。
严格来说,C++中甚至是代码> STD::vector:sisiz类型< /C> > /P>
令人惊讶的是,有多少C/C++开发人员仍然错误地理解了这一点。
示例(b)与示例(a)有不同的含义,编译器必须在编写时对其进行解释
如果(出于我无法想象的虚构原因),我编写了代码来实现这一点:
for( int i(0);i < vec.length(); ++i)
{
if(i%4 == 0)
vec.push_back(Widget());
}
for(int i(0);i
我真的不希望编译器优化每个对vec.length()的调用,因为我会得到不同的结果。这一个更好:
typedef vector<int> container; // not really required,
// you could just use vector<int> in for loop
for (container::const_iterator i = v.begin(); i != v.end(); ++i)
{
// do something with (*i)
}
typedef向量容器;//实际上不需要,
//可以在for循环中使用vector
for(container::const_迭代器i=v.begin();i!=v.end();++i)
{
//用(*i)做某事
}
- 我马上就能知道向量
没有被更新
- 任何人都知道发生了什么
这里
- 我知道有多少圈
v.end()
最后一个元素,因此没有开销
检查尺寸
- 易于为不同用户更新
容器或值类型
我很惊讶没有人说显而易见的:
在99.99%的情况下,这并不重要。
除非您使用的容器计算size()
是一项昂贵的操作,否则您的程序甚至会慢几纳秒都是不可理解的。我想说,在分析代码之前,请坚持使用可读性更强的容器,并发现size()
是一个瓶颈。让我们看看生成的代码(我使用MSVS2008进行了全面优化)
a
inti(0),iMax(vec.size());//vec是一个容器,比如std::vector
对于(;i
for循环产生2条汇编指令
b
for(int i(0);i
for循环生成8条汇编指令。vec.size()已成功内联
c
for(std::vector::const_迭代器i=vec.begin(),e=vec.end();i!=e;++i)
{
//环体
}
for循环生成15条汇编指令(所有指令都是内联的,但代码有很多跳转)
因此,如果您的应用程序是性能关键型的,请使用a)。否则b)或c)。(b)不会每次计算/调用该函数
--开始摘录----
循环不变代码运动:
GCC将循环不变代码运动作为其循环优化器的一部分以及部分冗余消除过程包括在内。这种优化从循环中删除指令,循环计算的值在循环的整个生命周期内不会改变
---结束摘录--
gcc的更多优化:
这里有两个问题需要讨论:
可变范围
终态再评价
可变范围
通常,不需要循环变量在循环外部可见。这就是为什么您可以在for
构造中声明它
终态再评价
Andrew Shepherd很好地说明了这一点:将函数调用放在结束条件中意味着不同的东西:
for( vector<...>::size_type i = 0; i < v.size(); ++i ) { // vector size may grow.
if( ... ) v.push_back( i ); // contrived, but possible
}
// note: this code may be replaced by a std::for_each construct, the previous can't.
for( vector<...>::size_type i = 0, elements = v.size(); i != elements; ++i ) {
}
for(vector::size_type i=0;i
应该注意迭代器示例:
for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
//loop body
}
for(vector::iterator it=vec.begin();it!=vec.end();it++){
//环体
}
如果循环体导致向量重新分配,则可能使循环迭代器“it”无效。因此,它并不等同于
for (int i=0;i<vec.size();++i){
//loop body
}
for(inti=0;i为什么不避开i
for( int i(0);i < vec.size(); ++i)
{
//loop body
}
for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end(); i != e; ++i)
{
//loop body
}
for( vector<...>::size_type i = 0; i < v.size(); ++i ) { // vector size may grow.
if( ... ) v.push_back( i ); // contrived, but possible
}
// note: this code may be replaced by a std::for_each construct, the previous can't.
for( vector<...>::size_type i = 0, elements = v.size(); i != elements; ++i ) {
}
for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
//loop body
}
for (int i=0;i<vec.size();++i){
//loop body
}
#include <boost/foreach.hpp>
std::vector<double> vec;
//...
BOOST_FOREACH( double &d, vec)
{
std::cout << d;
}