Для небольшого количества фактов приведен соответствующий текст из спецификаций
Оператор равенства (==,! =)
Указатели на объекты одного типаможно сравнить на равенство с «интуитивными» ожидаемыми результатами:
С § 5.10 стандарта C ++ 11:
Указатели одного типа(после преобразования указателя) можно сравнить на равенство.Два указателя одного типа сравниваются равными, если и только если они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес ( 3.9.2 ).
(пропуская подробности о сравнении указателей на член и константы нулевого указателя - они продолжают в той же строке «Делай, что я имею в виду»:)
- [...]Если оба операнда равны нулю, они сравниваются равными.В противном случае, если только один равен нулю, они сравниваются неравно. [...]
Самое «заметное» предостережение связано с виртуалами, и это тоже логично ожидать:
- [...] если любой из них является указателем на виртуальную функцию-член, результат не указан.В противном случае они сравниваются равными в том и только в том случае, если они ссылаются на один и тот же член одного и того же самого производного объекта (1.8) или того же подобъекта, если на них разыменовывается гипотетический объект связанного типа класса.[...]
Реляционные операторы (<,>, <=,> =)
С § 5.9 C ++Стандарт 11:
Можно сравнивать указатели на объекты или функции одного и того же типа (после преобразования указателей), причем результат определяется следующим образом:
- Если два указателя pи q одного и того же типа указывают на один и тот же объект или функцию, или оба указывают один за концом одного и того же массива, или оба равны null, тогда
p<=q
и p>=q
оба дают истину и p<q
и p>q
оба дают false. - Если два указателя p и q одного и того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или на разные функции, илиесли только один из них является нулевым, результаты
p<q,
p>q,
p<=q,
и p>=q
не определены . - Если два указателя указывают на нестатические элементы данныхтот же объект, или подобъектам или элементам массива таких членов, рекурсивно, указатель на объявленную позже мембрануr сравнивает большее, если два члена имеют одинаковый контроль доступа (пункт 11) и если их класс не является объединением.
- Если два указателя указывают на нестатические элементы данных одного и того же объекта с разным контролем доступа (Пункт 11) результат не указан.
- Если два указателя указывают на нестатические элементы данных одного и того же объекта объединения, они сравниваются равными (после преобразования в
void*
, если необходимо).Если два указателя указывают на элементы одного и того же массива или один за концом массива, указатель на объект с более высоким индексом сравнивается выше. - Другие сравнения указателей не определены.
Итак, если у вас было:
int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined
Также ОК:
struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Но это зависит от something
в вашем вопросе:
int g;
int main()
{
int h;
int i;
int *a = &g;
int *b = &h; // can't compare a <=> b
int *c = &i; // can't compare b <=> c, or a <=> c etc.
// but a==b, b!=c, a!=c etc. are supported just fine
}
Бонус: что еще есть в стандартной библиотеке?
§ 20.8.5 / 8 : "Для шаблонов greater
, less
,greater_equal
и less_equal
, специализации для любого типа указателя дают общий порядок, даже если встроенные операторы <
, >
, <=
, >=
не делают. "
Таким образом, вы можете глобально заказать любой нечетный void*
, если вы используете std::less<>
и друзей, а не голых operator<
.