Почему 2 неинициализированных std :: set :: iterator равны? - PullRequest
0 голосов
/ 07 октября 2019

Когда 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 ]

3 голосов
/ 07 октября 2019

Почему 2 неинициализированных std :: set :: iterator равны?

Они не инициализированы. Они являются инициализированными значениями. Итератор, инициализированный значением, является единственным: он не указывает ни на один контейнер.

Поведение чтения неинициализированного значения будет неопределенным, но это не то, что вы делаете в программе.

он не равен ни одному другому итератору в наборе

Сравнение входных итераторов определяется только для итераторов того же диапазона. Единственный итератор не указывает на тот же диапазон, что и любой не единственный итератор, поэтому сравнение не определено.

, но оно равно другим неинициализированным итераторам.

Два единственных числаитераторы всегда сравнивают равными.

Является ли это GCC-специфичной непереносимой реализацией?

Сравнение единственного итератора и не единственного числа не определено. Неопределенное поведение, как правило, «непереносимо», даже в пределах одной и той же версии компилятора (если только компилятор не определяет поведение, в этом случае оно непереносимо для других компиляторов).

Сингулярные итераторы в целом являются стандартными, поскольку C ++14 для всех прямых итераторов.

0 голосов
/ 07 октября 2019

вопрос: это специфично для GCC? Я НЕ спрашиваю, является ли это UB (это так!)

UB - это UB.

По определению, результат, который вы видите, потенциально уникален для этого конкретного прогона кода на этомконкретный день.

Даже если ни одна другая реализация никогда не проявляла такого поведения, это не имеет значения, потому что вы даже не можете полагаться на это на свое.

Хуже, полагаясь на него,вы нарушаете контракт, и другие части вашей программы могут нарушиться в результате .

Итак:

Является ли это специфичным для GCC, непереносимая реализация?

Да.

...