Приводит ли нуль-указатель к неопределенному поведению

Мне интересно, приводит ли следующий код к неопределенному поведению:

#include <cstddef>
#include <cstdio>

struct IA {
virtual ~IA() {}
int a = 0;
};
struct IB {
virtual ~IB() {}
int b = 0;
};
struct C: IA, IB {};

int main() {
C* pc = nullptr;
IB* pib = pc;
std::printf("%p %p", (void*)pc, (void*)pib);
}

15

Решение

Страуструп обсуждает этот случай в разделе 4.5 его документ о множественном наследовании 1989 года [PDF]:

Решение заключается в разработке операции преобразования (приведения) в
проверить значение указателя 0 […]

Дополнительная сложность и накладные расходы во время выполнения — это тест и
приращение.

Реализация явно проверяет наличие нулевых значений и гарантирует, что результатом приведения по-прежнему будет нулевое значение. Это было верно в C ++ 98 и не изменилось в C ++ 11 и nullptr,

Это особенно важно в случае нескольких базовых классов, где приведение производного класса к одному из базовых классов может потребовать изменения фактического значения указателя.

В вашем примере макет C в памяти будет сначала содержать байты для IAсопровождаемый байтами для IB, Кастинг в IA является trival, как указатель на начало C также будет указывать на начало IA часть C, Кастинг в IB с другой стороны, требует сдвига C указатель по размеру IA, Выполнение этого сдвига в случае nullptr приведет к ненулевому указателю после приведения, следовательно, особая обработка для нулей.

Как указал Ашеплер, соответствующий раздел в стандарте — [conv.ptr] §4.10:

Значение типа «указатель на резюме D«, где D это тип класса, может быть
преобразуется в значение типа «указатель на резюме B«, где B это база
класс D, […] Результатом преобразования является указатель на
подобъект базового класса объекта производного класса. Нулевой указатель
значение преобразуется в значение нулевого указателя типа назначения.

8

Другие решения

Обновление нулевого указателя четко определено, чтобы дать вам еще один нулевой указатель:

4.10p3:

Значение типа «указатель на резюме D«, где D является типом класса, может быть преобразован в значение типа «указатель на резюме B«, где B это базовый класс D, … Значение нулевого указателя преобразуется в значение нулевого указателя целевого типа.

9

По вопросам рекламы [email protected]