Элемент 28 Значение сравнения указателей в Общие знания C ++: основное промежуточное программирование ) объясняет ключ указателя объекта в C ++:
В C ++ объект может иметь несколько действительных адресов, и сравнение указателей не является вопросом адресов. Это вопрос об идентичности объекта.
Посмотрите на код:
class A{};
class B{};
class C: public A, public B {};
C c;
C* pc = &c;
B* pb = &c;
A* pa = &c;
class C
является производным от class A
и class B
, поэтому class C
равно class A
и class B
. объект C c
имеет 3 действительных адреса: адрес для class A
, class B
и class C
. Реализация зависит от компилятора, поэтому вы не можете предположить расположение памяти class C
, и это может выглядеть так:
---------- <- pc (0x7ffe7d10e1e0)
| |
---------- <- pa (0x7ffe7d10e1e4)
| A data |
---------- <- pb (0x7ffe7d10e1e8)
| B data |
----------
| C data |
----------
В приведенном выше случае, хотя значения адресов pc
, pa
и pb
не одинаковы, они все ссылаются на один и тот же объект (c
), поэтому компилятор должен убедиться, что pc
сравнивается равным pa
и pb
, т. е. pc == pa
и pc == pb
. Компилятор выполняет это сравнение, корректируя значение одного из сравниваемых указателей с помощью соответствующего смещения. Например,
pc == pa
переводится на:
pc ? ((uintptr_t)pc + 4 == (uintptr_t)pa) : (pa == 0)
Помимо прочего, поскольку A
и B
не имеют отношений наследования, мы не можем сравнивать pa
и pb
напрямую.
На ваши вопросы:
(1) does pa point to a valid A object?
(2) does pb point to a valid B object?
Yes, refer the above diagram.
(3) pc == (C*) pa ?
(4) pc == (C*) pb ?
Yes, No need to add (C*).
(5) does pa == pb ?
No. We can't compare them.