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

Безопасно ли #define NULL nullptr?

Я видел ниже макрос во многих верхних заголовочных файлах:

#define NULL 0  // C++03

Во всем коде NULL и 0 используются взаимозаменяемо. Если я изменю его на.

#define NULL nullptr  // C++11

Может ли это вызвать какой-либо плохой побочный эффект? Я могу думать о единственном (хорошем) побочном эффекте, поскольку следующее использование станет плохо сформированным;

int i = NULL;
4b9b3361

Ответ 1

Я видел ниже макроса в верхнем заголовочном файле:

Вы не должны этого видеть, стандартная библиотека определяет его в <cstddef><stddef.h>). И, согласно стандарту, IIRC, переопределение имен, определенных стандартными заголовочными файлами, приводит к поведению undefined. Поэтому с чисто стандартизированной точки зрения вы не должны этого делать.


Я видел, как люди делали следующее, по какой-то причине их сломанный ум думал:

struct X{
  virtual void f() = NULL;
}

(Как в [неверно]: "установите указатель виртуальной таблицы на NULL" )

Это справедливо только в том случае, если NULL определяется как 0, потому что = 0 является допустимым токеном для чисто виртуальных функций (§9.2 [class.mem]).

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

Однако будьте осторожны, что, даже если они, по-видимому, правильно используются, это изменится:

void f(int){}
void f(char*){}

f(0); // calls f(int)
f(nullptr); // calls f(char*)

Однако, если это было когда-либо, это было почти наверняка сломано.

Ответ 2

Намного лучше искать и заменять NULL на nullptr на протяжении всего кода.

Он может быть синтаксически безопасным, но где бы вы поместили #define? Это создает проблемы организации кода.

Ответ 3

Нет. Вам не разрешено (повторно) определять стандартные макросы. И если вы видите

#define NULL 0

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

Обратите внимание, что хорошие компиляторы обычно определяют NULL чем-то как:

#define NULL __builtin_null

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

Ответ 4

Вы не должны определять его вообще, если только вы не пишете собственную версию <cstddef>; это, безусловно, не должно быть в "многих верхних заголовочных файлах".

Если вы реализуете свою собственную стандартную библиотеку, то единственным требованием является

18.2/3 Макрос NULL представляет собой константу константы нулевого указателя С++

так что допустимо либо 0, либо nullptr, а nullptr лучше (если ваш компилятор поддерживает его) по той причине, которую вы даете.

Ответ 5

Возможно, не

Если у вас есть определенный формат поведения перегрузки:

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

Тогда поведение кода:

foo(NULL);

изменится в зависимости от того, изменен ли NULL на nullptr или нет.

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

Ответ 6

В то время как это может нарушить обратную совместимость со старыми вещами, которые были плохо написаны (или это, или слишком умное...), для вашего нового кода это не проблема. Вы должны использовать nullptr, а не NULL, где вы имеете в виду nullptr. Кроме того, вы должны использовать 0, где вы имеете в виду нуль.