c++使用for循环的最佳方法

发布于 2024-11-24 01:44:35 字数 441 浏览 0 评论 0原文

我脑子里一直盘旋着这个问题…… 我有一个 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( );
}

感谢您的建议!

I have this question that runs in my mind...
I have a std::vector to iterate:
which is the best way (the faster) to iterate?

here is the code using an iterator:

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

and here is 'normal' mode...

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

thanks for your suggestions!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

因为看清所以看轻 2024-12-01 01:44:36

两者实际上都不会更快,因为在大多数实现中,vector::iterator 只是 T*size 的 typedef代码> 已缓存。

但使用 ++it 而不是 it++ 是一个好习惯。后者涉及创建临时的。

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

在其他具有重要迭代器的容器(例如 maplist 等)上,后增量和预增量之间的差异可能会变得明显。

None of the two will be any faster really, because on most implementations a vector<T>::iterator is just a typedef for T* and size is cached.

But doing ++it instead of it++ is a good habit. The latter involves creating a temporary.

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

On other containers such as map, list etc. with nontrivial iterators the difference between postincrement and preincrement might become noticable.

薆情海 2024-12-01 01:44:36

如果您真的关心,您可以发现:只需使用该循环制作一个包含一个函数的单个源文件,然后查看优化后的程序集:

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

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

也就是说,您应该使用迭代器模式,因为它是理想的、通用的 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)

If you really care, you can find out: Just make a single source file with one function with that loop and look at the optimized assembly:

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

You can directly see the differences! I bet there are none.

That said, you should use the iterator pattern because it's idomatic, generic C++ and it gets you in the right mood -- plus, it works in far more general cases than just vectors! Write it like this:

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

In case you're curious, a vector iterator is most likely just going to be a native, raw pointer, so there's really nothing to fear in terms of efficiency, and a lot to be enjoyed from the self-explanatory, algorithmic style!

PS If you have C++0x, say it like this:

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

// or

for (const MyClass * & i : v)
咿呀咿呀哟 2024-12-01 01:44:36

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

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

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

  • 不要使用 it++,而是使用 ++it。这在 C++ 中非常重要,因为迭代器最终可能会在后增量中做更多的工作,而这些工作不会像 int 类型那样被优化。
  • 不要经常调用 end()size()。对于某些迭代器类型和集合,这可能不会被优化并且可能不是最佳的。
  • 当您需要 vector 的索引时,请使用 vector::size_typeint 不能保证足够大,而 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( );
}

The first code will decompose into incrementing a pointer. The second one will increment an index, and index into the array. The first one can use slightly smaller instructions (and thus potentially be faster) assuming the compiler doesn't optimize the second into the first already. But it will be a trivial difference.

Iterators should be preferred, however, not because of speed but because you can then easily move the code to iterate any standard C++ container, not just vector.

However, you've got a few things to improve.

  • Don't use it++, but ++it. This can be very important in C++ because iterators can end up doing a little more work in post-increment which won't be optimized out as if the type were an int.
  • Don't constantly call end() or size(). For some iterator types and collections this might not be optimized out and can be very sub-optimal.
  • Use vector::size_type when you need an index into a vector. int is not guaranteed to be big enough, while size_type was made specifically for that.

So, the better ways to write these are:

// 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( );
}
唠甜嗑 2024-12-01 01:44:36

这是我使用的:

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&R)
  6. 它不会对大多数编译器发出警告(与问题中使用的循环不同)

它也有一些缺点:

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

Here's what I use:

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

This loop has the following advantages over other approaches:

  1. it always looks the same (unlike the hacks that change from i++ to ++i)
  2. it's relatively short to write (compared to the iterator version)
  3. the int indexes are useful in your public interface (unlike iterators)
  4. it still always looks the same (unlike stdlib algorithms, where you need documentation to remember the parameters)
  5. it's very old and thus widely used. (originally comes from book "The C programming language" aka K&R)
  6. It doesn't give warnings on most compilers (unlike the loop that was used in the question)

It does have some disadvantages too:

  1. some newer programmers doesn't like it because they think C ways are too old
  2. in a const function, you might need to change it slightly to const T &o = vec[i]; or change the data member mutable
  3. type T changes depending on the use
千柳 2024-12-01 01:44:36

你可以这样做:

#include <iostream>
using namespace std;

int main() {
  for (int i = 3; i > 0; i--) {
    cout << i << "\n";
  }
  return 0;
}

source https://mockstacks.com/Cpp_For_Loop

You can do this:

#include <iostream>
using namespace std;

int main() {
  for (int i = 3; i > 0; i--) {
    cout << i << "\n";
  }
  return 0;
}

source https://mockstacks.com/Cpp_For_Loop

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文