C++:arr.size() 是循环的良好条件吗?
C++: Is arr.size() a good condition for a loop?
如果有一个名为arr的向量包含大量数据,我将打印该向量中的所有值。我会使用:
int arr_size = arr.size();
for(int i=0; i<arr_size; ++i) {//print the values}
或以这种方式实现它:
for(int i=0; i<arr.size(); ++i) {//print the values}
在我看来,第一种实现方式是将向量的大小获取到缓存中,从而使条件在第一次未命中后更快。第二次实现呢?慢吗?系统会在每次满足条件时调用 size(( 方法吗?
编辑:假设它正在使用C++。
推广带有树形体的循环,您给出的两个变体之间存在一个关键区别:如果arr
的大小在循环过程中发生变化怎么办?
对于第二种情况,如果编译器可以假设它不会更改,那么它可以优化循环,以便只调用一次arr.size()
并且生成的代码与第一种情况大致相同。
但是,如果循环体调用外部函数(极有可能(,那么它就不能再做出这种假设,并且必须检查arr.size()
每个循环迭代。
话虽如此,arr.size()
可能会解决一个简单的结构成员访问,这不会比将值存储在局部变量中慢,因此无论如何使用第一个变体都没有太多好处。 除非arr
是指针或引用,在这种情况下它是间接的,然后是访问,所以第一个版本会快一点。
如果这是一个特别常见的运行循环,并且由于某种原因您必须在没有优化的情况下进行编译,则可能需要使用第一种情况来加快速度。
但是,代码的可读性并没有因为多一行而受到太大损害,是吗?
总而言之,我会选择变体2,除非循环是一个必须紧的内部循环,在这种情况下,我会选择变体 1 以确保。
当然,如果将元素添加到循环内部的arr
并且循环需要覆盖这些元素,那么只有第二个变体是正确的。
我建议你是否可能使用迭代器而不是索引。 例如:
在 C++ 中:
for( const_iterator it = arr.begin(), ite = arr.end();
it != ite; ++it)
{
....
}
在 c# 中:
foreach(var item in arr){....}
c++的一个优点是当你有list而不是vector时,在vector size((中是O(1(,但在list中它是O(n(。此外,这可以防止调用的情况,arr。大小((太多次。
通常的优点是 C# 和 C++ 中的代码更具可读性,但在某些情况下仍然无法使用它们,您应该使用索引。
第二个选项更好:
for(int i=0; i<arr.size(); ++i) {//print the values}
循环结束后将释放变量 i。arr.size(( 将在循环初始化后计算。不会分配内存来存储arr_size变量。
如果你有一个足够现代的编译器:
for (auto i: arr)
{
//print the values
}
或者更好的是...避免滚动自己的for
循环(这也适用于 C++11 之前的编译器(:
std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, ","));
-
std::copy()
正在<algorithm>
-
std::ostream_iterator<>
在<iterator>
.
我做了一些测试,缓存这些值似乎比每次迭代评估条件要好[略好]。
这是我使用 std::vector
时的测试结果。
代码:使用 std::vector 测试 for 循环缓存计时结果(评估和缓存运行各运行 4 次(:
Evaluated:
- Compilation time: 2,16 sec, absolute running time: 10,94 sec, absolute service time: 13,11 sec
- Compilation time: 1,76 sec, absolute running time: 9,98 sec, absolute service time: 11,75 sec
- Compilation time: 1,76 sec, absolute running time: 10,11 sec, absolute service time: 11,88 sec
- Compilation time: 1,91 sec, absolute running time: 10,62 sec, absolute service time: 12,53 sec
Cached:
- Compilation time: 1,84 sec, absolute running time: 9,55 sec, absolute
service time: 11,39 sec
- Compilation time: 1,75 sec, absolute running
time: 9,85 sec, absolute service time: 11,61 sec
- Compilation time:
1,83 sec, absolute running time: 9,41 sec, absolute service time:
11,25 sec
- Compilation time: 1,86 sec, absolute running time: 9,87
sec, absolute service time: 11,73 sec
这是我使用 std::list
时的测试结果。
代码:使用 std::list 测试 for 循环缓存计时结果(评估和缓存运行各 2 次运行(:
Evaluated:
- Compilation time: 1,9 sec, absolute running time: 17,94 sec, absolute service time: 19,84 sec
- Compilation time: 1,84 sec, absolute running time: 17,52 sec, absolute service time: 19,36 sec
Cached:
- Compilation time: 1,81 sec, absolute running time: 17,74 sec, absolute service time: 19,56 sec
- Compilation time: 1,92 sec, absolute running time: 17,29 sec, absolute service time: 19,22 sec
绝对运行时间是我用作比较指标的指标。缓存条件始终(但略微(优于评估条件。
- 如何在for循环中包含两个索引值的测试条件
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 即使没有满足他们的条件,我也无法通过一些 do-while 循环
- 在循环条件 i<sqrtN(预先计算)和 i*i<N 中,C++哪个更有效?
- 尽管条件为真,循环仍停止
- 为什么我不能在 for 循环中出现这样的条件?(C++)
- C++ 即使不满足条件,循环也会终止
- 具有迭代器和自定义步长的循环结束条件
- 有没有办法在循环中的条件至少满足一次时运行语句?
- 为什么循环没有中断,并且 if 条件没有按预期工作?
- 为什么我不能将 size() 函数编写为 while 循环中的条件?
- 虽然循环即使应用了错误条件也不会退出
- 当循环在条件C++之前停止工作时
- Leetcode C++用于循环条件
- 当满足条件时,While循环未结束
- 对于检查 >=0 终止条件时的循环索引类型
- 调用以条件循环(c++)
- 使用布尔条件c++循环时无法退出
- 在条件C++循环语句中向SQLite3表中插入条目