Почему бы не назвать nullptr NULL?

В С++ 11 ключевое слово nullptr было добавлено как константа нулевого указателя более безопасного типа, так как предыдущее общее определение NULL как 0 имеет некоторые проблемы.

Почему комитет по стандартам решил не называть новую константу нулевого указателя NULL или объявить, что NULL должен быть #define d до nullptr?

Ответ 1

Стефан Т. Лававей (член комитета по стандарту С++) объяснил, что однажды в talk (55:35):

В то время как для реализации разрешено #define NULL nullptr, это может нарушить некоторые виды использования, такие как

int i = NULL;

и, видимо, их много. Поэтому они не смогли заставить изменения.

Ответ 2

nullptr имеет тип указателя, в то время как NULL имеет тенденцию быть целочисленным, и иногда в перегруженных функциях вам нужно понимать, что вы используете указатель, а не целое число - это когда nullptr пригодится.

Таким образом, чтобы действительно ответить на ваш вопрос, NULL и nullptr служат двум различным целям, и переопределение одного в другое, вероятно, сломает много вещей в уже существующих базах кода.

Кроме того, проверьте это на веб-сайте Бьярна Страуструпа:

Должен ли я использовать NULL или 0?

В C++ определение NULL равно 0, поэтому существует только эстетический разница. Я предпочитаю избегать макросов, поэтому я использую 0. Еще одна проблема с NULL в том, что люди иногда ошибочно полагают, что это другое от 0 и/или не целое число. В стандартном коде NULL был/есть иногда определяется для чего-то неподходящего и поэтому должен был/должен быть избегать. Это менее распространено в наши дни. Если вы должны назвать ноль указатель, назовите его nullptr; то, что он назвал в C++ 11. Затем, "nullptr" будет ключевым словом.

Ответ 3

Без фактического участия в обсуждении в комитете по стандартизации трудно сказать наверняка, но я бы подумал, потому что он сломал бы некоторый код, который использует NULL в значении, где nullptr недостаточно совместимо. И нарушение старого кода никогда не является хорошей идеей.

Ответ 4

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

За мгновение вы можете сделать:

void* p = 0;

но не это без неявного кастинга:

void* p = 1234;

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

nullptr улучшите это, применяя указатель, вы не можете назначить это целое число. Поскольку поведение изменено, для обратной совместимости создается новое имя.

Также обратите внимание, что nullptr обрабатывается компилятором, его фактическое значение не отображается пользователю (например, нуль в случае NULL). Гораздо проще иметь зависимое от архитектуры значение, скажем 0xdeadbeef, без изменения логики кода программиста.

Ответ 5

Почему комитет по стандартам решил не называть новую константу нулевого указателя NULL

Предположительно, потому что новый нулевой указатель - это ключевое слово, а ключевые слова не могут быть #defined, поэтому его вызов NULL сделал бы включение любого заголовка C., который был бы плохо сформирован.

или объявить, что NULL должен быть #defined до nullptr?

Комитет по стандартам позволяет NULL быть #defined до nullptr, но он не требует его.

С++ 11 18.2 Типы [support.types]/2: Макрос NULL представляет собой константу нулевого указателя С++, определенную реализацией, в этом Международном стандарте.

С++ 11 4.10 Конверсии указателей [conv.ptr]/1: Константа нулевого указателя представляет собой целочисленное константное выражение (5.19) prvalue целочисленного типа, которое оценивается в 0 или значение класса std::nullptr_t.

Обратная совместимость здесь не является проблемой, любое использование NULL, предполагающее, что это форма целого числа 0, не является стандартным согласным. Реализации могут предпочесть не делать этого, чтобы оправдывать такое злобное поведение.

Ответ 6

Я продемонстрирую случай, когда решение определить nullptr как другой тип помогает предотвратить ошибки.

Рассмотрим следующие функции:

void foo(int);
void foo(char *);

int main()
{
    foo(NULL); // oops
}

В С++ 98 приведенный выше код вызывает функцию foo (int), потому что NULL заменяется на 0, что, скорее всего, не то, что вы намеревались.

Но если вы вызываете foo (nullptr), он вызывает правильный - foo (char *).

Ответ 7

nullptr вводится для безопасности типов и для ясности (возможно, для остановки инициализации типов без указателей с помощью NULL).

NULL (тип int) не изменяется на nullptr (тип указателя), чтобы избежать путаницы и обеспечить обратную совместимость.

Таким образом, стандартный ход мысли, вероятно, связан с плавным переходом от старой к новой нотации, не вызывая двусмысленности или тормозя любой уже существующий код.