为什么 2 个未初始化的 std::set::迭代器相等?

How come 2 uninitialized std::set::iterator are equal?

本文关键字:set 迭代器 std 初始化 为什么      更新时间:2023-10-16

std::set<>::iterator未初始化时,它等于集合中的任何其他迭代器,但它等于其他未初始化的迭代器。

这是特定于 GCC 的实现吗?(未初始化的迭代器是否实际初始化为无效值?

#include <stdio.h>
#include <iostream>
#include <set>
#include <vector>
int main()
{
std::set<int> s;
std::set<int>::reverse_iterator inv = s.rend();
std::cout << (inv == s.rend()) << "n";
std::cout << (inv == s.rbegin()) << "n";
s.insert(5);
std::cout << (inv == s.rend()) << "n";
std::cout << (inv == s.rbegin()) << "n";
// invalidate
inv = std::set<int>::reverse_iterator();
std::cout << (inv == s.rend()) << "n";
std::cout << (inv == s.rbegin()) << "n";
auto inv2 = std::set<int>::reverse_iterator();
std::cout << (inv == inv2) << "!!!n";
return 0;
}

指纹:

1
1
0
1
0
0
1!!!

现场示例:https://onlinegdb.com/r1--46u_B

为什么 2 个未初始化的 std::set::迭代器相等?

它们不是未初始化的。它们是值初始化的。值初始化迭代器是单数的:它不指向任何容器。

读取未初始化值的行为是未定义的,但这不是您在程序中所做的。

它不等于集合中的任何其他迭代器

输入迭代器之间的比较仅针对相同范围的迭代器定义。奇异迭代器不指向与任何非奇异迭代器相同的范围,因此比较是未定义的。

但它等同于其他未初始化的迭代器。

两个奇异迭代器总是相等。

这是特定于 GCC 的、不可移植的实现吗?

将奇异迭代器与非奇异迭代器进行比较是不确定的。未定义的行为通常是"不可移植的",即使在同一个编译器版本中也是如此(除非编译器指定了行为,在这种情况下,它不能移植到其他编译器(。

自 C++14 以来,奇异迭代器通常是所有前向迭代器的标准。

问题是

:这是GCC特定的吗?我不是在问这是否是UB(它是!

UB 是 UB。

根据定义,您看到的结果对于该特定日期的特定代码运行可能是唯一的。

即使没有其他实现表现出这种行为,这也没关系,因为你甚至不能依赖它。

更糟糕的是,通过依赖它,您正在破坏合同,并且程序的其他部分可能会因此而中断。

所以:

这是特定于 GCC 的、不可移植的实现吗?

是的。