比较循环的不同类型的C++

Comparing different types of C++ for-loops

本文关键字:C++ 同类型 比较 循环      更新时间:2023-10-16

C++非常灵活,我想更深入地理解循环操作。我希望能很好地比较每个实现以及什么更好/更快/更高效。此外,学习其他实现for循环的方法也是一种福利,而不一定是STL中的东西。

我在寻找专家的答案,而不是意见。注意我对答案的许多限制:答案只涉及提到的特定for循环,它们的限制(可能不是直观的),STL中没有的特定替代方案,以及特定的增强。

这些其他for循环(而不是"传统")如何以不同/更好的方式工作?

循环的其他"非传统"限制是什么?

示例1)传统的循环是:

for(int i=0;i<SIZE;i++){
    //do something for each iteration;
}

例2)现在假设我有一个分数向量。

vector<int> scores = {77,91,100,88,85,68,95};
for (auto it = scores.begin(); it != scores.end(); ++it){
    //do something for each iteration;
}

示例3)相同的分数矢量,不同的循环。

for (auto& x: scores) //do something for each iteration;

我对示例3特别感兴趣,因为它太简单了,我不确定它到底在做什么,但功能与其他两个相同。

  1. 您可以访问i,可以使用它来判断您是在第一次、最后一次还是其他迭代中。不适用于非随机访问容器,因此对于必须与向量和列表类似地工作的泛型代码来说,这不是一个选项。从c++标准的第一个版本开始支持。

  2. 适用于所有标准迭代器,因此适用于泛型代码。没有访问迭代计数器,但计数可以用std::distance计算,但是,如果迭代器不是随机访问,那么这就增加了迭代的复杂性。不过,弄清楚您是在第一次迭代中还是在最后一次迭代中仍然是恒定的时间。从c++标准的第一个版本开始支持。

  3. 更好的语法,但在语义上等同于2的某些形式。不能使用子范围:始终从开始到结束(除非您突破)。无法访问迭代计数器。在c++11之前不存在。也存在基于宏的实现,如BOOST_FOREACH,它们做类似的事情并支持旧的标准。

迭代范围可以与基于范围的for循环一起使用,以绕过这一点。它们不是标准库的一部分,但也有第三方实现。


TL;博士

  1. 当您需要迭代器计数而不需要泛型代码时,这很方便
  2. 用于c++11之前的通用代码
  3. 由于其简单性,默认情况下是一个不错的选择

版本3基本上是对版本2的简短表述。

右侧scores上的项必须支持std::begin(scores)std::end(scores),并且在语法上也变得等效:

  for (auto& x: scores)
  {
      // STUFF
  }
  // Is the same as:
  for(auto tmp = std::begin(scores); tmp != std::end(scores); ++tmp)
  {
      auto& x = *tmp;
      // tmp not technically available.
      // STUFF
  }

当您不想访问数组中的每个元素或有多个循环变量时,normal for循环非常有用。

for (int i = 0, j = 2; i != 10; ++i, ++j) { ... }

来自Herb Sutter的博客:

基于范围的for循环是访问每个一个范围的元素。

// C++98
for( vector<int>::iterator i = v.begin(); i != v.end(); ++i ) {
    total += *i;
}
// C++11
for( auto d : v ) {
    total += d;
}