编译器/JIT 优化 Java 和 C++ 中 for 循环的边界检查
Compiler/JIT optimisation of bounds check of for loop in Java and C++
我从 C# 中for
和while
循环的答案中了解到:">只要您在条件中使用arr.Length
,编译器/JIT 就会针对此方案进行优化:">
for(int i = 0 ; i < arr.Length ; i++) {
Console.WriteLine(arr[i]); // skips bounds check
}
这让我怀疑java编译器是否有这样的优化。
for(int i=0; i<arr.length; i++) {
System.out.println(arr[i]); // is bounds check skipped here?
}
我认为确实如此,嗯,是吗?使用像ArrayList
这样的Collection
时也会发生同样的情况吗?
但是,如果我必须在 for 循环的主体中使用 myList.size()
的值,考虑到现在myList
是一个 ArrayList,该怎么办?所以在这种情况下,吊装myList.size()
无济于事,因为size()
是方法调用?例如,可能是这样的:
int len = myList.size(); // hoisting for using inside the loop
for(int i = 0; i < myList.size(); i++) { // not using hoisted value for optimization
System.out.println(myList.get(i));
if(someOtherVariable == len) {
doSomethingElse();
}
}
编辑:虽然我还没有得到java的答案,但我仍然在为这个问题添加第二部分。
问:C++ (C++98/C++11( 是否有此类优化,例如针对vector.size()
和string.size()
?例如,哪个在性能方面更好?
for (int i = 0; i < myvector.size(); ++i)
cout << myvector[i] << " "; // is bounds checking skipped here, like in C#?
或
// does this manual optimisation help improve performance, or does it make?
int size = myvector.size();
for (int i = 0; i < size; ++i)
cout << myvector[i] << " ";
也就是说,这种优化是否也存在于std::string
?
Java
从 Java 7 开始,编译器消除了对原始数组的边界检查,如果它可以证明无法进行越界访问。在Java 7之前,JIT或AOT编译器可以做到这一点。对于JIT和AOT编译器,它不限于for (int i = 0; i < arr.length; i++)
,它可以将边界检查移动到循环之外,例如for (int i = 0; i < 10000000; i++)
,将其减少为单个检查。如果该检查失败,它将运行具有完整边界检查的代码版本,以在正确的位置引发异常。
对于集合,它要复杂得多,因为边界是由调用方法检查的,而不是在调用的位置。通常,它不能从字节码中消除,但如果 JIT 和 AOT 编译器可以内联方法(这取决于对象的实例化方式和存储位置等,因为 Java 中的所有非私有方法都是虚拟的,因此编译器需要确保它不需要虚拟调用(,但我不知道他们是否真的这样做。
C++
C++ 不检查 operator []
中的边界。当您使用 at
时,它会检查边界。 at
是内联的,因此它取决于特定的编译器及其标志,但通常,编译器可以删除边界检查,如果它可以证明无法进行越界访问。它还可以将边界检查移到循环之外,但它仍然需要保证异常将在正确的位置抛出,所以我不知道是否有任何异常。
C++的两个示例在执行死代码消除的编译器中都是等效的,假设您在for
循环后不使用int size
。如果您使用某些未内联的方法,后者可能会更快。(你也可以把size
的定义放在初始化里面:for (int i = 0, size = myvector.size(); i < size; ++i)
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么我的for循环不能正确获取argv
- 在基于范围的for循环中使用结构化绑定声明
- 通过for循环使用用户输入填充列表
- 使用for循环检查数组中的重复项
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 正在使用for循环创建QScatterSerie
- Python中的for循环与C++有何不同
- 在更改for循环的第三部分后,未使用for循环结果
- 在 for 循环中查找问题时遇到困难
- 嵌套for循环C++的问题(初学者)
- 如何用for循环在c++中生成单词三角形
- 如何在for循环中包含两个索引值的测试条件
- 带有多个独立参数的C++For循环
- C++ Python 循环"for i, num in enumerate(list):"版本
- C 多循环 for () 基础知识
- 没有条件值的 FOR 循环"for (int i = 1; ; i++)"无法正常工作
- 为用户提供循环for循环的选项
- 打破循环for循环