Урок №81. Нулевые указатели

  Юрий  | 

  |

  Обновл. 13 Сен 2021  | 

 114344

 ǀ   9 

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

Нулевое значение и нулевые указатели

Помимо адресов памяти, есть еще одно значение, которое указатель может хранить: значение null. Нулевое значение (или «значение null») — это специальное значение, которое означает, что указатель ни на что не указывает. Указатель, содержащий значение null, называется нулевым указателем.

В языке C++ мы можем присвоить указателю нулевое значение, инициализируя его/присваивая ему литерал 0:

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

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

Разыменование нулевых указателей


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

В этом есть смысл, ведь разыменование указателя означает, что нужно «перейти к адресу, на который указывает указатель, и достать из этого адреса значение». Нулевой указатель не имеет адреса, поэтому и такой результат.

Макрос NULL

В языке Cи (но не в C++) есть специальный макрос препроцессора с именем NULL, который определен как значение 0. Хоть он и не является частью языка C++, его использование достаточно распространено, и должно работать в каждом компиляторе С++:

Однако, поскольку NULL является макросом препроцессора и, технически, не является частью C++, то его не рекомендуется использовать.

Ключевое слово nullptr в C++11


Обратите внимание, значение 0 не является типом указателя, и присваивание указателю значения 0 для обозначения того, что он является нулевым — немного противоречиво, вам не кажется? В редких случаях, использование 0 в качестве аргумента-литерала может привести к проблемам, так как компилятор не сможет определить, используется ли нулевой указатель или целое число 0:

Для решения этой проблемы в C++11 ввели новое ключевое слово nullptr, которое также является константой r-value.

Начиная с C++11, при работе с нулевыми указателями, использование nullptr является более предпочтительным вариантом, нежели использование 0:

Язык C++ неявно преобразует nullptr в соответствующий тип указателя. Таким образом, в вышеприведенном примере, nullptr неявно преобразуется в указатель типа int, а затем значение nullptr присваивается ptr.

nullptr также может использоваться для вызова функции (в качестве аргумента-литерала):

Совет: В C++11 используйте nullptr для инициализации нулевых указателей.

Тип данных std::nullptr_t в C++11

В C++11 добавили новый тип данных std::nullptr_t, который находится в заголовочном файле cstddef. std::nullptr_t может иметь только одно значение — nullptr! Хотя это может показаться немного глупым, но это полезно в одном случае. Если вам нужно написать функцию, которая принимает аргумент nullptr, то какой тип параметра нужно использовать? Правильно! std::nullptr_t. Например:

Вам, вероятно, никогда это не придется использовать, но знать об этом стоит (на всякий пожарный).


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (442 оценок, среднее: 4,89 из 5)
Загрузка...

Комментариев: 9

  1. Владимир:

    с этими указателями….какие-то скороговорки для мозга..

  2. somebox:

    Так и не понял, для чего нужен std::nullptr_t. Зачем его ввели.

    1. Алексей:

      Судя по тому, что я узнал за 81 урок и какое мнение сложилось о С++, ответ на Ваш вопрос: "просто так, на всякий пожарный"))))))

      ps. 3 допустимых вида инициализации переменных, значит, вас не смущают?)))))

      1. Фото аватара Юрий:

        В этих уроках объясняется как база, так и нюансы, которые вы, скорее всего, не очень часто будете использовать на практике, но знать об этом стоит.

    2. C++11:

      Каждая переменная или константа должна быть определенного типа.
      Следовательно, у nullptr (как константы, а не ключевого слова) тоже должен быть какой-то тип.
      В MSDN есть пример, показывающий зачем ввели дополнительный тип:

      Например, если для функции func(std::pair<const char *, double>) произвести вызов func(std::make_pair(NULL, 3.14)), возникнет ошибка времени компиляции. Макрос NULL разворачивается в 0, поэтому вызов std::make_pair(0, 3.14) возвращает значение std::pair<int, double>, которое невозможно преобразовать к типу параметра std::pair<const char *, double> функции func(). Вызов func(std::make_pair(nullptr, 3.14)) успешно компилируется, поскольку std::make_pair(nullptr, 3.14) возвращает значение std::pair<std::nullptr_t, double>, которое допускает преобразование в тип std::pair<const char *, double>.

      >> https://docs.microsoft.com/ru-ru/cpp/cpp/nullptr
      >> https://msdn.microsoft.com/ru-ru/windows/desktop/jj651642

      Зачем еще оно нужно:
      Приходите на собеседование, и дают вам такой код 😉

      Из http://www.cyberforum.ru/cpp-beginners/thread638684.html#post3365236
      Ответ: http://ideone.com/Av14Ae

    3. Борис:

      Зачем он нужен — понятно (см. конец). Непонятно — зачем кому-то писать функцию, принимающую этот nullptr как параметр? Он же не несёт никакую информацию в функцию.

      1. Павел:

        Вроде я допёхал. Он нужен тупо для вызова функции без каких либо значений. Ну к примеру для проги выше нам надо объявит переменную, затем присвоить ей значение и только после этого засунуть её в функцию. Примерно так:

        То есть + 2 строчки из которых 1 указатель, а второй переменная, а так мы тупо без каких либо объявлений пихаем эти значения и функция выполняется. Как я понимаю используется в чём то типо кнопок.

    4. Алексей:

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

      Грубый пример:

      Это позволит не выполнять лишних действий если указатель=nullptr.

      p.s. Если это вам не понятно, то дочитайте эти уроки до конца и вернитесь сюда.

  3. Benya:

    Можете добавить примеры с применением нулевых указателей, в там числе с передачей тех в функцию как аргумент?

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *