Продекларированные, но ещё не инициализированные, т.е. заготовленные заранее для работы в будущем, переменные-указатели надо сразу инициализировать соответствующим нулевым значением – 0
, NULL
или nullptr
, т.к. в дальнейшем могут возникнуть проблемы из-за того, что, если значение не было присвоено, то указатель по-умолч. будет указывать на произвольный адрес, содержимым которого является мусор. Разыменование указателей с мусором приведет к неожиданным результатам. В большинстве случаев получится сбой в программе. К слову, с разыменованием нулевого указателя дела обстоят так же несмотря на то, что нулевой указатель не имеет адреса, но его хотя бы можно проверить на «нулёвость».
class Foo { Some* bar; };
Сразу после создания объекта класса Foo
в поле bar
уже что-то находится без явной инициализации, поэтому дальнейшие проверки работают неправильно:
if (bar) {}
if (bar == 0) {}
if (bar == NULL) {}
if (bar == nullptr) {}
Никакая проверка не работает, т.к. поле bar
уже есть какой-то произвольный (мусорный) адрес.
Оставлять указатели без инициализации (Some* bar;
) – плохая идея! Инициализируйте указатели нулевым значением, если перед первым использованием не собираетесь присваивать им другие значения.
Если же явно задать пустое значение любым из след. способов:
Some* bar = NULL;
Some* bar = 0;
Some* bar = nullptr;
то след. проверки работают:
if (!bar) {}
if (bar == nullptr) {}
if (bar == 0) {}
if (bar == NULL) {}
Макрос препроцессора NULL
и значение 0
равнозначны, потому что NULL
это алиас для 0
. В большинстве IDE при наведении курсора на NULL
в интелеснс можно увидеть специальный макрос препроцессора: «#define NULL 0
«, что определён в заголовочном файле «stddef.h» стандартной библиотеки C. Т.е. NULL
это и есть 0
, т.к. при компиляции препроцессор макрос NULL
в коде заменяет на 0
. Так обстоят дела в языке C, но не в C++.
Хоть макрос препроцессора NULL
и не является частью языка C++, но его использование достаточно распространено, и работает в каждом компиляторе С++. Однако, поскольку NULL
является макросом препроцессора в C, и технически не является частью C++, то его не рекомендуется использовать в C++.
При инициализации указателя «ничем» (до введения в C++11 nullptr) писали 0
(Some* bar = 0;
). Бытовало мнение, что это просто короче, чем писать NULL
(«Some* bar = NULL;
«), якобы кроме длины разницы больше никакой нет. По этой причине делается многое, напр., никто не пишет явные сравнения «bar == NULL
«, «bar != nullptr
«, а вместо этого пишут просто «bar
» или «!bar
«, чтобы было короче и быстрее, но в случае NULL
и 0
это не решающий фактор. На самом деле разница куда больше. Дело не только в краткости. Макрос препроцессора NULL
не входит в стандарт C++, но всё же работает в большинстве компиляторов, но его использование не рекомендуется.