【问题标题】:What's the recommended way of iterating a container in C++11?在 C++11 中迭代容器的推荐方法是什么?
【发布时间】:2012-02-05 23:23:43
【问题描述】:

在 C++11 中迭代容器的推荐方式是什么?

使用

container.begin() and container.end()

或者

begin(container) and end(container)

如果有的话,什么时候比另一个更受欢迎?

【问题讨论】:

  • 您的示例与迭代本身无关。这是关于如何从作为容器模型的类的对象中获取迭代器。
  • 目前还没有足够的经验来推荐方法。新的 for 语法和 begin/end free 函数有优势,但经验可能会告诉你一些缺点(我期望没有,但我没想到大部分经验的教导,即使我期望有一些)。跨度>

标签: c++ algorithm stl c++11


【解决方案1】:

我认为range based for loops的新语法

 for (auto item : container)

大概是最喜欢C++11了。

正如其他人评论的那样,您有时需要auto&const auto& 而不是auto

【讨论】:

  • @Basile:我同意,但 VS10 还不支持,所以我还没有玩过它。 :)
  • @spraff:同意,但问题(故意?)含糊不清,我的回答很合适!
  • 我会以这些项目作为参考:auto& item : container,以避免不必要的复制。
  • @Johann:那么如果你想要 VS10 支持,你就真的不需要 C++11。
  • @spraff:我不同意,标题谈到迭代容器,基于范围的 for 循环肯定会迭代容器,同时保护您免受任何其他循环可能遭受的许多微小错误的影响。 OP 提供的代码示例并不真正涉及迭代容器(更多从中获取迭代器...),但问题仍然存在。
【解决方案2】:

更好的方法是

begin(container)
end(container)

因为它更具可扩展性。例如,模板参数推导可用于确定静态数组的大小,因此begin(my_static_array)end(my_static_array) 将起作用。

更一般地说,您可以向 begin(.) end(.) 添加重载/特化,并在泛型算法中使用不可变的遗留类型。

如果你自己编写一个通用算法,你真的只需要担心这个

template <typename T>
void foo (T & t)
{
    bar (begin(t), end(t)); // certainly better than bar(t.begin(), t.end())
}

在客户端代码中,这并不重要。事实上,我会说不要在那种情况下使用新的形式——我喜欢在某些情况下保留某些样式/习语,划分我的心态。但这只是我。

for (auto i = c.begin(); i != c.end(); ++i)
   // I can see at-a-glance that c is a STL-style container.
   // That might be useful to know. I can probably dismiss static arrays
   // and unorthodox containers as possibilities.
   foo (i, c.size());

【讨论】:

  • 为什么要在这里引用迭代器?
  • 如果要启用对数组的迭代,则必须编写 std::begin(t)std::end(t),或者必须编写 using std::begin;using std::end; 作为前两个语句函数(有点像using std::swap 成语)。
  • @spraff:作为推荐的习惯用法,我希望在for 循环的第一条语句期间“缓存”c.end() 的结果,而不是在每次迭代时计算它。
  • @MatthieuM.,或者我可以让编译器担心微优化并拒绝用噪音来装饰我的答案。
  • @spraff:认为你不知道它是否是微优化。如果end 调用不能被内联,并且如果编译器不能证明它的纯​​度(非常罕见......),则不会执行优化。
猜你喜欢
  • 2014-03-13
  • 1970-01-01
  • 2021-07-10
  • 2019-09-15
  • 2017-06-28
  • 2016-06-13
  • 2021-11-16
  • 2015-11-09
  • 2010-11-16
相关资源
最近更新 更多