可以在for循环中优化i = v.end()吗?

Adr*_*ian 8 c++ c++11

我刚刚看到这样的事情:

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

这样做更好:

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

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

Yak*_*ont 7

是的,第二个版本可以更优化,只要您的容器永远不会被修改编译器无法告诉容器永远不会被修改.

通过检查基于C++ 11 ranged的循环,可以找到"最优"的循环结构for.

代码:

for( auto x : vec_expression ) {
  // body
}
Run Code Online (Sandbox Code Playgroud)

大致翻译成:

{
  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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

其中任何以开头__为目的的变量仅用于展示目的,并且在内部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);
  }
}
Run Code Online (Sandbox Code Playgroud)

这是这样使用的:

foreach( vec_expression, [&]( int x ) {
} );
Run Code Online (Sandbox Code Playgroud)

它不会让你破坏或返回到外部范围,但它非常接近C++ 11基于范围的.

如果你缺少基于范围的for和lambdas,你可能是一个完全疯狂的人并将上面的大部分实现为宏... std::begin使用辅助功能完成前面的工作,以避免污染功能的身体,mayhap .


vin*_*nes 5

最有可能的是优化器会为你完成这项工作.

顺便问一下,为什么decltype(x.begin())什么时候有auto你呢?

for (auto i = x.begin(); i != x.end(); ++i)
{
  // do stuff
}
Run Code Online (Sandbox Code Playgroud)

甚至:

for (auto i : x)
{
  // do stuff
}
Run Code Online (Sandbox Code Playgroud)

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