2015-10-19 145 views
5

如果我有函数调用在这样的循环状态:函数调用for循环条件?

for (auto it = s.begin(); it != s.end(), ++it) {} 

叫在每次迭代?我希望是的。编译器是否允许优化它呢?目前的编译器是否足够聪明以做到这一点?或者我更好地使用类似以下的东西:

for (auto it = s.begin(), auto end = s.end(); it != end; ++it) {} 

+0

当您使用C++ 11时,请考虑使用基于范围的for循环来避免此问题。 –

+0

@NeilKirk在我的情况下不可用,我实际上需要迭代器来做有趣的事情。 – Paladin

+1

我个人使用第二种方法编写循环,然后我不必担心它。我不知道它在实践中有多重要或不重要。 –

回答

4

是的,程序必须在每次迭代中调用第二个表达it != s.end()。我认为编译器可以在某些情况下优化它。

无论如何,不​​要编译器的工作。如果它可以被优化,编译器就有很大的机会做到这一点,并且无论如何这个调用没有显着的性能影响。

如果情况允许,你应该使用基于for循环的范围:

for (auto& i : s) { 
    // instructions 
} 

这样,编译器有更多的机会来优化你的代码,它是更容易阅读。

如果你想了解一下编译器可以优化多少东西的例子,看看这个! http://ridiculousfish.com/blog/posts/will-it-optimize.html

+0

我通常会使用它,但实际上我需要操纵迭代器,所以经典的foreach循环对我来说不起作用 – Paladin

+0

啊,然后使用循环的经典。但是再次,编译器非常聪明。在这种情况下,不需要复杂的代码。 –

+0

我编辑我的答案是更通用的,我只是添加了一个伟大的文章的链接。 –

6

for (auto it = s.begin(); it != s.end(), ++it) 

s.begin()只调用一次。
s.end()operator++()(对于++it)在循环的每次迭代中被调用。

编译器允许优化它吗?

根据编译器,实现和优化级别,编译器可以优化掉s.end()的调用。如果能优化掉operator++()的电话,我会感到惊讶。

当前的编译器足够聪明吗?

无法回答。

还是我更好地使用类似以下内容:

for (auto it = s.begin(), auto end = s.end(); it != end; ++it) {} 

它不会伤害。但是,如果在循环中修改s,则可能会出现问题。如果s未在循环中修改,我会建议使用此方法。

1

是的,它在每次迭代中被正式调用。是的,目前的编译器可能会内联该函数,并且每次看到s.end()返回相同的值(指针?)。

除非分析显示这是程序中的瓶颈(极不可能),否则不需要复杂的代码。