【问题标题】:How exactly iterators are being compared?究竟是如何比较迭代器的?
【发布时间】:2020-07-06 10:59:45
【问题描述】:
#include <iostream>
#include <set>
using namespace std;
int main() {
  set<int> numbers;
  numbers.insert(1);
  auto numbers_find = numbers.find(1);
  auto numbers_end = numbers.end();
  cout<<*numbers_find<<endl;
  cout<<*numbers_end<<endl;
  cout<<(numbers_find==numbers_end?"true":"false")<<endl;
  return 0;
}

在这种情况下,输出将是

1
1
false

据我所知,迭代器基本上是指针,但仅适用于 STL 集合的元素。 所以我的问题是——当我们比较两个迭代器时,到底在比较什么,我认为这是指针指向的某种地址的等价物。但是,根据指针逻辑,如果两个迭代器指向同一个元素,那么它们相等就有意义。

int a = 5;
int *ptr1 = &a;
int *ptr2 = &a;
cout<<((ptr1==ptr2)?"true":"false")<<endl;

输出

true

附: 链接到上面的代码示例https://repl.it/@VanyaRyanichev/FrillyPapayawhipMonitor#main.cpp

【问题讨论】:

  • 取消引用结束迭代器是否与您的问题相关?你不能那样做。
  • *numbers_end 是 UB。就像int *ptr2 = &amp;a + 1; cout &lt;&lt; *ptr2; /* how come it prints 1 but ptr1 == ptr2 is false? */
  • @VanyaRyanichev 它指向第一个元素的末尾,即它指向不存在的第二个元素。由于没有第二个元素,因此取消引用它是 UB
  • 进入实现细节(可能会有所不同),std::set 是一个二叉搜索树。 std::set::iterator 是一个内部保存指向树节点的指针的类。当您比较迭代器时,您会比较这些指针。 std::set::end() 指向某个哨兵节点并且不能被取消引用,因为该哨兵节点不是“完整”节点并且不保存任何用户数据,而只有 leftrightparent 指针。跨度>
  • @Vanya Ryanichev 请检查此en.cppreference.com/w/cpp/container/set/end。您可以直观地观察结束指针。

标签: c++ iterator std


【解决方案1】:

结束迭代器不指向最后一个元素,它不指向任何东西。您的程序格式不正确(具有未定义的行为)。

C++ 将序列表示为half-open intervals

【讨论】:

  • 显然这是非常简单的事情,但是*numbers_end 怎么给我们1 ???
  • 未定义的行为意味着任何事情都可能发生。显然,在您的情况下,会返回一个值 1。就我而言,我遇到了崩溃(MSVC 2019)。
  • @VanyaRyanichev,不,在内部它不指向最后一个元素。将1 替换为12 即可。
  • @VanyaRyanichev,但是当您插入12 时,输出为1。行为未定义,任何事情都可能发生。
  • @VanyaRyanichev 好的,但是您似乎坚持认为它有时会返回一个类似于您放入容器中的值的值。只要您有未定义的行为,将其与 anything 进行比较是没有意义的。
猜你喜欢
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 2021-12-04
  • 2011-12-31
  • 1970-01-01
  • 2013-12-05
相关资源
最近更新 更多