-1

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

4

2 回答 2

3

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

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

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

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

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

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

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

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

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

自 C++14 以来,对于所有前向迭代器,单数迭代器通常是标准的。

于 2019-10-07T14:22:19.060 回答
0

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

UB就是UB。

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

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

更糟糕的是,依赖它,您正在违反合同,并且您的程序的其他部分可能因此而中断

所以:

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

是的。

于 2019-10-07T14:28:40.103 回答