之前已经问过类似于此问题的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()?
答案 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()
的结果,如果它可以推断出结果在循环的整个生命周期内都不会改变。这不是一个微不足道的优化。如果速度很关键,我就不会依赖编译器来制作它。将优化显式化会更安全,更清晰,因此查看代码时不必怀疑是否存在错失的优化机会。
另一方面,如果速度不是问题(通常不是),我就不会为微优化而烦恼。即使速度是一个问题,您仍应首先分析您的代码,并确保在应用任何优化之前,这行代码实际上是一个瓶颈。一般来说,这是一个很好的经验法则。