Подтвердить что ты не робот

NULL макрос или NULL const

В настоящее время я читаю книгу на С++, и в этой книге автор объясняет, что лучше использовать макрос константы, а не NULL, но не объяснять причину или давать какие-либо преимущества или недостатки.

Так почему это лучше использовать:

const int NULL = 0;
int *ptr = NULL;

вместо:

int *ptr = NULL;

Единственное объяснение заключается в том, что макрос NULL не является безопасным для типов.

4b9b3361

Ответ 1

Все устарели.

Используйте nullptr вместо этого. Это особое значение для указателя, который не указывает ни на что. Он даже имеет свой собственный тип, std::nullptr_t.

Нет гарантии, что адрес 0x0 соответствует значению "неинициализированного" указателя, но обратите внимание, что буквальное значение 0 гарантируется преобразованием в значение нулевого указателя.

Ответ 2

Если вы используете С++ 11, тогда рекомендуется использовать nullptr вместо NULL.

Ниже приведены несколько строк из Язык программирования С++ по Bjarne Stroustrup

  • В более раннем коде вместо nullptr обычно используется 0 или NULL (§7.2.2). Однако использование nullptr устраняет потенциальную путаницу между целыми числами (такими как 0 или NULL) и указателями (такими как nullptr).
  • существуют различия в определении NULL в разных реализациях; например, NULL может быть 0 или 0L. В C NULL обычно (void *) 0, что делает его незаконным в С++ (§7.2.1):
  • Использование nullptr делает код более читаемым, чем альтернативы, и позволяет избежать путаницы, когда функция перегружена, чтобы принять либо указатель, либо целое число

Надеюсь, это поможет вам понять.

Ответ 3

Автор прав, что макросы препроцессора не печатаются (в противоположность, например, переменным, где ввод текста применяется во время их объявления). Таким образом, макросы более опасны в этом отношении, так как компилятор не может проверить правильность текста в выражениях, и вы можете пропустить важное предупреждение/сообщение об ошибке во время компиляции

Конечно, создатели компилятора могут (и, как правило, делать, я надеюсь) предоставить версию NULL-макроса, которая расширяется до значения с литым, эквивалентным (не идентичным!) Определению C:

#define N ((void*)0)

BTW: поскольку С++ 11 NULL может оценивать тип std:: nullptr_t.

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

Для краткого упражнения вы можете попробовать следующее, чтобы увидеть, что макросы не имеют типа, поэтому их тип выводится в выражениях, с учетом, например, арифметические преобразования или рекламные акции. В приведенном ниже примере макросы MY_NULL (= без кастинга) приводят к довольно опасным назначениям. Это то, что имеет в виду ваш автор книг и пытается вас предупредить.

Макросы MY_TYPED оценивают кастированные выражения, что гарантирует, что компиляторы поймают ошибку при попытке, например. i = MY_TYPED_NULL;

#define MY_NULL 0
#define MY_TYPED_NULL ((void*)0)
int i;
float f;
void* v;
i = MY_NULL;    // bad: no compiler error
f = MY_NULL;    // bad: no compiler error
v = MY_NULL;    // seems to match programmer intention
i = MY_TYPED_NULL;    // good: compiler error
f = MY_TYPED_NULL;    // good: compiler error
v = MY_TYPED_NULL;    // correct

Ответ 4

Действительно, "NULL macro" не безопасен для типов. Это означает, что ваш компилятор не знает, используете ли вы правильный тип. Например, при использовании memcpy:

SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));

(взято из там)

Компилятор видит только два указателя в памяти. Но SomeClass и AnotherClass являются неполными типами.

Как говорили другие, если вы можете использовать С++ 11, просто используйте nullptr.