8

我刚才看到了这样的东西:

vector<int> x { 1, 2, 3, 4 };
for (auto i = x.begin(); i != x.end(); ++i)
{
  // do stuff
}

这样做更好吗:

vector<int> x { 1, 2, 3, 4 };
for (auto i = x.begin(), end = x.end(); i != end; ++i)
{
  // do stuff
}

我想我认为优化器会处理这个问题。我错了吗?

4

3 回答 3

7

是的,第二个版本可能更优化,只要您的容器从未被修改过,但编译器无法告诉容器从未被修改过。

通过检查 C++11 基于范围的循环可以找到“最佳”循环结构for

编码:

for( auto x : vec_expression ) {
  // body
}

大致翻译为:

{
  auto&& __container = vec_expression;
  using std::begin; using std::end;
  auto&& __end = end(container)
  for( auto __it = begin(container); __it != __end; ++__it ) {
    auto x = *__it;
    {
      // body
    }
  }
}

其中任何以开头的变量__仅出于说明目的而存在,并且using std::begin; using std::end;// body. (请记住,包含的任何变量__都是为编译器实现保留的)。

如果您的编译器支持 lambda,您可以编写自己的版本:

template<typename Container, typename Lambda>
void foreach( Container&& c, Lambda&& f ) {
  using std::begin; using std::end;
  auto&& e = end(c);
  for( auto it = begin(c); it != e; ++it ) {
    f(*it);
  }
}

像这样使用:

foreach( vec_expression, [&]( int x ) {
} );

它不会让你中断或返回外部范围,但它非常接近基于 C++11 的范围。

如果您同时缺少基于范围的 for 和 lambda,那么您可能是一个完全疯狂的人,并将上述大部分内容作为宏实现...std::begin使用具有完美转发功能的辅助函数来完成工作,以避免污染函数的主体,也许.

于 2013-09-20T02:47:25.620 回答
5

优化器很可能会为您完成这项工作。

顺便说一句,为什么decltype(x.begin())auto你?

for (auto i = x.begin(); i != x.end(); ++i)
{
  // do stuff
}

甚至:

for (auto i : x)
{
  // do stuff
}

后者是range forhttp ://en.cppreference.com/w/cpp/language/range-for 。

于 2013-09-20T02:19:18.867 回答
1

你不应该。因为某些操作erase可能会使迭代器无效。

如果您确定循环内没有此类操作for,请随意这样做。但通常编译器会为您进行优化。(如果您打开优化标志)

于 2013-09-20T02:25:16.360 回答