使用基于范围的for循环在某范围内迭代

许多编程语言都支持for循环的一种变体,称作for each,即在集合的每个元素上重复一组相同语句。直到C ++ 11,C++才对此提供核心语言支持。 此前最接近的功能是来自标准库std::for_each的通用算法,该算法将函数应用于范围内的所有元素。C++ 11为实际上称为基于范围的for循环提供了语法上的支持。 新的C++ 17标准对原始语言功能进行了一些改进。

做好准备

在C++ 11中,基于范围的for循环具有以下常规语法:

for ( range_declaration : range_expression ) loop_statement

为了举例说明使用基于范围的for循环的每种方式,我们将使用以下函数返回元素序列:

std::vector<int> getRates() 
{ 
  return std::vector<int> {1, 1, 2, 3, 5, 8, 13}; 
} 

std::multimap<int, bool> getRates2() 
{ 
  return std::multimap<int, bool> { 
    { 1, true }, 
    { 1, true }, 
    { 2, false }, 
    { 3, true }, 
    { 5, true }, 
    { 8, false }, 
    { 13, true } 
  }; 
}

怎么做……

基于范围的for循环可以多种方式使用:

  • 通过为序列的元素指定特定的类型:
auto rates = getRates();
for (int rate : rates) 
  std::cout << rate << std::endl; 
for (int& rate : rates) 
  rate *= 2;
  • 通过不指定类型而是让编译器推导它:
for (auto&& rate : getRates()) 
  std::cout << rate << std::endl; 

for (auto & rate : rates) 
  rate *= 2; 

for (auto const & rate : rates) 
  std::cout << rate << std::endl;
  • 通过在C++ 17中使用结构化绑定和分解声明:
for (auto&& [rate, flag] : getRates2()) 
  std::cout << rate << std::endl;

这个如何起作用……

使用此实现后,前面显示的基于范围的for循环将按预期进行编译和执行。执行依赖于参数的查找时,编译器将识别我们编写的两个begin()和end()函数(它们引用了dummy_array),因此生成的代码将变为有效。

在前面的示例中,我们定义了一个迭代器类模板和两个别名模板,分别称为dummy_array_iterator和dummy_array_const_iterator。对于这两种类型的迭代器,begin()和end()函数都具有两个重载。这是必要的,以便我们考虑的容器可以在基于范围的常量和非常量实例的循环中使用:

template <typename T, const size_t Size> 
void print_dummy_array(dummy_array<T, Size> const & arr) 
{ 
  for (auto && e : arr) 
  { 
    std::cout << e << std::endl; 
  } 
}

为该系列文章中涉及的简单范围类为基于范围的for循环启用一种可能的替代方法是提供成员begin()和end()函数。通常,只有拥有并可以修改源代码,这才有意义。另一方面,该系列文章中显示的解决方案在所有情况下均适用,并且应优先于其他替代方案。

参见

  • 为自定义类型启用基于范围的for循环

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据