Безопасно ли #define NULL nullptr?
Я видел ниже макрос во многих верхних заголовочных файлах:
#define NULL 0 // C++03
Во всем коде NULL
и 0
используются взаимозаменяемо. Если я изменю его на.
#define NULL nullptr // C++11
Может ли это вызвать какой-либо плохой побочный эффект? Я могу думать о единственном (хорошем) побочном эффекте, поскольку следующее использование станет плохо сформированным;
int i = NULL;
Ответы
Ответ 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
, где вы имеете в виду нуль.