c ++用于循环的最佳方式

时间:2011-07-15 11:03:03

标签: c++ for-loop iteration stdvector

我有这个问题在我脑海里浮现...... 我有一个std :: vector迭代: 这是迭代的最佳方式(更快)?

这是使用迭代器的代码:

// using the iterator
for( std::vector <myClass*>::iterator it = myObject.begin( ); it != myObject.end( ); it++ )
{
    (*it)->someFunction( );
}

这是'正常'模式......

// normal loop
for( int i = 0; i < myObject.Size( ); i++ )
{
    myObject[i]->someFunction( );
}

感谢您的建议!

4 个答案:

答案 0 :(得分:6)

两者中的任何一个都不会更快,因为在大多数实现中,vector<T>::iterator只是T*的typedef而缓存了size

但是++it代替it++是一个好习惯。后者涉及创建一个临时的。

for(std::vector <myClass*>::iterator it = myObject.begin( );
                           it != myObject.end( );
                           ++it)
                           ^^^^  

maplist等其他容器上使用非平凡的迭代器,后增量和预增量之间的差异可能会变得明显。

答案 1 :(得分:5)

如果您真的关心,您可以找到:只需使用该循环创建一个带有一个函数的源文件,然后查看优化的程序集:

g++ -O2 -S -o ver1.s ver1.cpp
g++ -O2 -S -o ver2.s ver2.cpp

你可以直接看到差异!我打赌没有。

那就是说,你应该使用迭代器模式,因为它是idomatic,通用的C ++,它让你处于正确的心情 - 而且,它在更常见的情况下工作,而不仅仅是矢量!写得像这样:

typedef std::vector<MyClass*> myVec;
for (myVec::const_iterator it = v.begin(), end = v.end(); it != end; ++it)
{
  const MyClass & x = **it;
  /* ... */
}

如果你很好奇,矢量迭代器最有可能只是一个本地的原始指针,所以在效率方面真的没有什么可担心的,并且从不言自明的算法中可以享受很多东西。风格!

PS如果您有C ++ 0x,请这样说:

for (auto it = v.cbegin(), end = v.cend(); it != end; ++it)

// or

for (const MyClass * & i : v)

答案 2 :(得分:1)

第一个代码将分解为递增指针。第二个将增加一个索引,并索引到数组中。第一个可以使用略小的指令(因此可能更快),假设编译器没有将第二个优化为第一个。但这将是一个微不足道的差异。

迭代器应该是首选,但不是因为速度,而是因为您可以轻松地移动代码来迭代任何标准C ++容器,而不仅仅是vector

但是,你还有一些需要改进的地方。

  • 请勿使用it++,而是使用++it。这在C ++中非常重要,因为迭代器最终可以在后增量中做更多的工作,而不会优化,就像类型是int一样。
  • 请勿经常致电end()size()。对于某些迭代器类型和集合,这可能不会被优化,并且可能非常不理想。
  • 当您需要vector::size_type的索引时,请使用vectorint并不能保证足够大,而size_type是专门为此做的。

因此,更好的方法是:

// using the iterator
for(std::vector <myClass*>::iterator it = myObject.begin( ), end = myObject.end(); it != end; ++it)
{
    (*it)->someFunction( );
}

// normal loop
for(std::vector <myClass*>::size_type i = 0, size = myObject.size(); i < size; ++i)
{
    myObject[i]->someFunction( );
}

答案 3 :(得分:0)

以下是我使用的内容:

int s = vec.size();
for(int i=0;i<s;i++)
{
    T &o = vec[i];
    ...
}

与其他方法相比,此循环具有以下优势:

  1. 它总是看起来一样(不同于从i ++变为++ i的黑客)
  2. 写入相对较短(与迭代器版本相比)
  3. int索引在您的公共接口中有用(与迭代器不同)
  4. 它看起来总是一样(与stdlib算法不同,你需要文档来记住参数)
  5. 它很老,因此被广泛使用。 (最初来自“C编程语言”又名K&amp; R)
  6. 它不会在大多数编译器上发出警告(与问题中使用的循环不同)
  7. 它也有一些缺点:

    1. 一些新的程序员不喜欢它,因为他们认为C方式太旧了
    2. 在const函数中,您可能需要稍微更改为const T&amp; o = vec [i];或更改数据成员mutable
    3. 类型T根据用途而变化