Значения указателей по-умолч. NULL, 0 и nullptr в C и C++

Продекларированные, но ещё не инициализированные, т.е. заготовленные заранее для работы в будущем, переменные-указатели надо сразу инициализировать соответствующим нулевым значением – 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;). Бытовало мнение, что это просто короче, чем писать NULLSome* bar = NULL;«), якобы кроме длины разницы больше никакой нет. По этой причине делается многое, напр., никто не пишет явные сравнения «bar == NULL«, «bar != nullptr«, а вместо этого пишут просто «bar» или «!bar«, чтобы было короче и быстрее, но в случае NULL и 0 это не решающий фактор. На самом деле разница куда больше. Дело не только в краткости. Макрос препроцессора NULL не входит в стандарт C++, но всё же работает в большинстве компиляторов, но его использование не рекомендуется.