使用C ++ 11基于范围的正确方法是什么?

时间:2013-04-10 13:19:52

标签: c++ c++11 foreach

使用C ++ 11基于范围的for

的正确方法是什么?

应该使用什么语法? for (auto elem : container), 还是for (auto& elem : container)for (const auto& elem : container)? 还是其他一些?

3 个答案:

答案 0 :(得分:11)

使用for (auto elem : container)for (auto& elem : container)for (const auto& elem : container)没有正确方法。你只是表达你想要的东西。

让我详细说明一下。我们走一走吧。

for (auto elem : container) ...

这个是语法糖:

for(auto it = container.begin(); it != container.end(); ++it) {

    // Observe that this is a copy by value.
    auto elem = *it;

}

如果容器中包含复制成本低廉的元素,则可以使用此方法。

for (auto& elem : container) ...

这个是语法糖:

for(auto it = container.begin(); it != container.end(); ++it) {

    // Now you're directly modifying the elements
    // because elem is an lvalue reference
    auto& elem = *it;

}

如果要直接写入容器中的元素,请使用此选项,例如。

for (const auto& elem : container) ...

这个是语法糖:

for(auto it = container.begin(); it != container.end(); ++it) {

    // You just want to read stuff, no modification
    const auto& elem = *it;

}

正如评论所说,只是为了阅读。就是这样,如果使用得当,一切都是“正确的”。

答案 1 :(得分:7)

正确的方法总是

for(auto&& elem : container)

这将保证保留所有语义。

答案 2 :(得分:1)

虽然range-for循环的最初动机可能是容易迭代容器的元素,但语法足够通用,即使对于非纯粹容器的对象也是如此。

for循环的语法要求是range_expression支持begin()end()作为任一函数 - 作为其计算类型的成员函数或非成员函数接受类型实例的内容。

作为一个人为的例子,可以使用以下类生成一系列数字并迭代该范围。

struct Range
{
   struct Iterator
   {
      Iterator(int v, int s) : val(v), step(s) {}

      int operator*() const
      {
         return val;
      }

      Iterator& operator++()
      {
         val += step;
         return *this;
      }

      bool operator!=(Iterator const& rhs) const
      {
         return (this->val < rhs.val);
      }

      int val;
      int step;
   };

   Range(int l, int h, int s=1) : low(l), high(h), step(s) {}

   Iterator begin() const
   {
      return Iterator(low, step);
   }

   Iterator end() const
   {
      return Iterator(high, 1);
   }

   int low, high, step;
}; 

使用以下main功能

#include <iostream>

int main()
{
   Range r1(1, 10);
   for ( auto item : r1 )
   {
      std::cout << item << " ";
   }
   std::cout << std::endl;

   Range r2(1, 20, 2);
   for ( auto item : r2 )
   {
      std::cout << item << " ";
   }
   std::cout << std::endl;

   Range r3(1, 20, 3);
   for ( auto item : r3 )
   {
      std::cout << item << " ";
   }
   std::cout << std::endl;
}

将获得以下输出。

1 2 3 4 5 6 7 8 9 
1 3 5 7 9 11 13 15 17 19 
1 4 7 10 13 16 19