#опытным
Для многих nullptr - это магическая хреновина, которая магически и правильно "зануляет"(что бы это не значило) указатель. А как это работает - уже не важно. И даже на этом уровне понимания можно прекрасно писать хороший код и не знать забот. Но мы здесь собрались для грокания С++, поэтому будем разбираться.
Для начала, nullptr - это литерал указателя. Есть литералы целочисленые(
42, -100), есть литералы строковые("123", "qwerty"), а есть литерал указателя и nullptr - его единственный представитель. Литерал - это prvalue.Этот литерал обозначает константу нулевого указателя. То есть при присваивании указателю nullptr'а, он зануляется. Происходит это потому что существует неявное преобразование nullptr к значению нулевого указателя любого указательного типа.
Но это не единственная константа нулевого указателя. Есть также литералы
0 и NULL.У каждого литерала есть свой тип. У nullptr это std::nullptr_t. А у
0 и NULL - int. И этом кроется вся суть:void g(int*)
{
std::cout << "Function g called\n";
}
int main()
{
g(nullptr); // Fine
g(NULL); // Fine
g(0); // Fine
// But
auto null1 = nullptr;
auto null2 = NULL;
auto null3 = 0;
g(null1); // Fine
g(null2); // ERROR: non-literal zero cannot be a null pointer constant
g(null3); // ERROR: non-literal zero cannot be a null pointer constant
}
Как только мы присвоили NULL или 0 какой-то переменной, они потеряли способность инициализировать указатели. Потому что они просто стали какой-то переменной типа int, а какими-то рандомными числами очень странно инициализировать указатели.
Но с nullptr другая штука. null1 - это переменная типа std::nullptr_t. И здесь нет никакой неоднозначности. Этот тип придуман для того, чтобы представлять нулевой указатель. Он больше ни для чего не нужен. Поэтому также есть неявные преобразование любых значений типа std::nullptr_t к значению нулевого указателя. Это значит, сколько бы раз не был прокинут nullptr в разные переменные, он всегда будет означать именно нулевой указатель.
Don't be ambiguous. Stay cool.
#cpp11