【问题标题】:Are all end() iterators equivalent for a collection type?所有 end() 迭代器都等效于集合类型吗?
【发布时间】:2013-01-13 13:45:04
【问题描述】:

在 C++ 中给定一个特定的 stl 集合,end() 值对于相同模板化的所有实例是否等效?换句话说,以下内容是否适用于所有 stl 容器和环境(不仅适用于 std::map)?

std::map<Key, Value> foo(int seed);

std::map<Key, Value> instance1 = foo(1);
std::map<Key, Value> instance2 = foo(2);
std::map<Key, Value>::iterator itr = instance1.begin();
std::map<Key, Value>::iterator endItr = instance2.end(); // Comes from other collection!

for (; itr != endItr; ++itr) {
  // Do something on each key value pair...
}

【问题讨论】:

  • 可能在特定的实现中工作,但您只能将其计入使用默认 ctor 创建“结束”迭代器的类型(例如,std::istream_iterator)。即使在这些情况下,也没有什么可以直接保证。
  • 如果这行得通,请认为自己不走运。这显然是您的代码中的一个错误。我认为 MSVC 会检测到这种类型的迭代器误用,但也许这只是检查过的迭代器。
  • @SteveTownsend:我认为这可以保证在 MSVC 上工作,因为它们实现了SCARY iterators
  • @Jesse:不完全是。 SCARY 迭代器允许您混合迭代器类型,而不管比较器/分配器类型如何,因此std::map&lt;K,V&gt;::iteratorstd::map&lt;K,V, custom_compare&gt;::iterator 的类型相同,但这并不意味着来自两个映射的结束迭代器具有相同的值。跨度>
  • @DaveS:啊,对,SCARY 迭代器只讨论类型等价而不是值等价。谢谢指正。

标签: c++ stl iterator containers language-lawyer


【解决方案1】:

自己试试吧:

#include <map>
#include <iostream>
using namespace std;
map<int,int> m1;
map<int,int> m2;

int main() {
  cout<<(m1.end() == m2.end())<<endl;
}

http://ideone.com/o18DtQ

输出:

0

【讨论】:

    【解决方案2】:

    不,因为 STL 容器和迭代器的要求:

    23.2.1 一般容器要求 [container.requirements.general]

    6 begin() 返回一个指向第一个元素的迭代器 容器。 end() 返回一个迭代器,它是过去的值 为容器。如果容器是空的,那么 begin() == end();

    24.2.1 一般 [iterator.requirements.general]

    6 当且仅当,迭代器 j 被称为从迭代器 i 可达 表达式 ++i 有一个有限的应用序列 使 i == j。如果 j 可以从 i 到达,它们指的是 相同的顺序。

    begin()end() 对于空容器的相等性意味着 begin()end() 需要是相同容器对象的一部分,因此 end() 不能是容器类的静态成员。另请注意 - 除了前向迭代器 - 在 end() 上应用 operator-- 将无法使用静态 end() 迭代器解决。

    【讨论】:

    • 你怎么知道这行不通?如果std::map::end 返回的对象对于某个专业的所有地图都相同,该怎么办?
    • @mfontanini:我们能不能只将未定义的行为视为“不工作”的同义词?每次都要拼出来吗?
    • @BenjaminLindley 好吧,这是一个合理的问题,最终标准将其说明
    • @K-ballo 为什么不呢?请举例
    • @rhalbersma:还记得 C++ 是如何允许您重载运算符的吗?
    【解决方案3】:

    一般来说,不,那是不可移植的。它可能在某些平台上巧合。

    有一些末端迭代器可以重复用于不同的范围,例如默认构造的 istream_iterator:

    ifstream a("foo.txt");
    ifstream b("bar.txt");
    istream_iterator<string> end;
    istream_iterator<string> ia( a);
    istream_iterator<string> ib( b);
    // from here on both [ia, end> and [ib, end> are valid ranges.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 2013-01-21
      相关资源
      最近更新 更多