这个for循环会在每次迭代时调用set.size()(set是一个向量)吗?

时间:2014-10-16 03:10:31

标签: c++ optimization

之前已经问过类似于此问题的question,它没有确定的接受答案。

这个for循环会在每次迭代时调用 set.size() set 是一个向量)吗?

for(int i = 0; i < set.size(); i++) 

代码会更快吗?

int size = set.size();  
for(int i = 0; i < size; i++)

VS 2010编译器是否足够聪明,不允许程序在每次迭代时调用 .size()

2 个答案:

答案 0 :(得分:3)

通常,现代优化编译器可以进行非常强大的优化。自己做这样的优化是非常值得的,通常你只是进入编译器的方式。在您查看优化代码之前,您应该对代码进行分析,以确定性能问题是什么。

使用此代码godbolt (see live code)进行快速测试:

void function() {
  std::set<int> set ;
  set.insert( 10 ) ;
  set.insert( 20 ) ;

   for(int i = 0; i < set.size(); i++) 
   {
     printf( "%d\n", i ) ;
   }
}

显示它正在直接访问count变量而不进行函数调用,相关的程序集是:

movq    $0, 56(%rsp)    #, MEM[(struct _Rb_tree_impl *)&set]._M_node_count

cmpq    %rbx, 56(%rsp)  # ivtmp.115, MEM[(long unsigned int *)&set + 40B]

所以至少在这个简单的情况下,gcc优化器似乎能够做你想做的快速技巧。虽然生成的代码不同clang似乎也在做类似的事情。

更新

问题已更新,提到Visual Studio。

我不知道生成Visual Studio程序集的在线工具,否则我也会检查它,但如果Visual Studio也执行类似的优化,我也不会感到惊讶。我们可以看到优化肯定是可能的。生成assembly in Visual Studio之后,确定是否每次循环迭代都会调用size()

答案 1 :(得分:3)

编译器可能足够聪明,可以缓存set.size()的结果,如果它可以推断出结果在循环的整个生命周期内都不会改变。这不是一个微不足道的优化。如果速度很关键,我就不会依赖编译器来制作它。将优化显式化会更安全,更清晰,因此查看代码时不必怀疑是否存在错失的优化机会。

另一方面,如果速度不是问题(通常不是),我就不会为微优化而烦恼。即使速度是一个问题,您仍应首先分析您的代码,并确保在应用任何优化之前,这行代码实际上是一个瓶颈。一般来说,这是一个很好的经验法则。