在 C++11 中,我们可以在迭代容器时使用更简单的“for”循环,如下所示:
for (auto i : {1, 2, 3, 4})
...;
Run Code Online (Sandbox Code Playgroud)
但是,我不知道此类代码的效率。具体来说:
更新:假设我们使用-O2,并且循环中的代码只是几个操作。就我而言,我想枚举四个方向 UP DOWN LEFT RIGHT 并使用方向参数调用一个函数。我只关心程序是否可以具有最佳性能。
非常感谢!
{1, 2, 3, 4} 的类型是什么?
std::initializer_list将从该初始化程序构造。那是被迭代的。你甚至需要包括<initializer_list>它才能工作。
编译器会展开循环吗?
该语言不保证循环展开。您可以通过编译和检查生成的程序集,找出特定编译器是否使用特定目标 CPU 的特定选项展开特定循环。
这就是说,迭代的次数在编译时是已知的,并且因此可以为编译器展开整个循环。
假设我们使用 -O2
值得一提的是,-O2 不启用-funroll-loops。在添加该选项之前,请阅读其文档:
-funroll-loops
展开循环,其迭代次数可以在编译时或进入循环时确定。-funroll-loops 意味着 -frerun-cse-after-loop。此选项会使代码更大,并且可能会也可能不会使其运行得更快。
在这个例子中,Clang 确实展开了循环:https : //godbolt.org/z/enKzMh而 GCC 没有展开:https : //godbolt.org/z/ocfor8
不能保证,但编译器可以优化某些情况,因此您最终得到好的代码的可能性很高。
例如,可以完全优化掉:
#include <initializer_list>
// Type your code here, or load an example.
int sum() {
int sum = 0;
for (auto i : {1, 2, 3, 4}) {
sum += i;
}
return sum;
}
int main() {
return sum();
}
Run Code Online (Sandbox Code Playgroud)
用 编译-O3,gcc 可以推导出计算结果为 10:
sum():
mov eax, 10
ret
main:
mov eax, 10
ret
Run Code Online (Sandbox Code Playgroud)
在实际示例中,编译器可能无法对其进行优化,因此您必须自己验证。