Что такое nullptr c
nullptr (C++/CLI and C++/CX)
The nullptr keyword represents a null pointer value. Use a null pointer value to indicate that an object handle, interior pointer, or native pointer type does not point to an object.
Use nullptr with either managed or native code. The compiler emits appropriate but different instructions for managed and native null pointer values. For information about using the ISO standard C++ version of this keyword, see nullptr.
The nullptr keyword is equivalent to Nothing in Visual Basic and null in C#.
Usage
The nullptr keyword can be used anywhere a handle, native pointer, or function argument can be used.
The nullptr keyword is not a type and is not supported for use with:
throw nullptr (although throw (Object^)nullptr; will work)
The nullptr keyword can be used in the initialization of the following pointer types:
Windows Runtime handle
Managed interior pointer
The nullptr keyword can be used to test if a pointer or handle reference is null before the reference is used.
Function calls among languages that use null pointer values for error checking should be interpreted correctly.
Example: nullptr keyword
The following code example demonstrates that the nullptr keyword can be used wherever a handle, native pointer, or function argument can be used. And the example demonstrates that the nullptr keyword can be used to check a reference before it is used.
Example: Use nullptr and zero interchangeably
The following code example shows that nullptr and zero can be used interchangeably on native pointers.
Example: Interpret nullptr as a handle
The following code example shows that nullptr is interpreted as a handle to any type or a native pointer to any type. In case of function overloading with handles to different types, an ambiguity error will be generated. The nullptr would have to be explicitly cast to a type.
Example: Cast nullptr
The following code example shows that casting nullptr is allowed and returns a pointer or handle to the cast type that contains the nullptr value.
Example: Pass nullptr as a function parameter
The following code example shows that nullptr can be used as a function parameter.
Example: Default initialization
Example: Assign nullptr to a native pointer
Requirements
Compiler option: (Not required; supported by all code generation options, including /ZW and /clr )
10.9 – Нулевые указатели
Нулевые значения и нулевые указатели
Как и обычные переменные, указатели не инициализируются при создании экземпляров. Если указателю значение не присвоено, он по умолчанию будет указывать на какой-то мусорный адрес.
Помимо адресов памяти, есть еще одно дополнительное значение, которое может содержать указатель: нулевое значение. Нулевое значение – это специальное значение, которое означает, что указатель ни на что не указывает. Указатель, содержащий нулевое значение, называется нулевым указателем.
В C++ мы можем присвоить указателю нулевое значение, инициализировав или присвоив ему литерал 0:
Лучшая практика
Если при создании вы не присваиваете указателям какое-либо значение, инициализируйте их нулевым значением.
Косвенное обращение через нулевые указатели
В предыдущем уроке мы отметили, что косвенное обращение через мусорный указатель приведет к неопределенным результатам. Косвенное обращение через нулевой указатель также приводит к неопределенному поведению. В большинстве случаев это приведет к сбою вашего приложения.
Концептуально в этом есть смысл. Косвенное обращение через указатель означает «перейти по адресу, на который указывает указатель, и получить доступ к значению там». У нулевого указателя нет адреса. Что делать, когда вы пытаетесь получить доступ к значению по этому адресу?
Макрос NULL
В C++ есть специальный макрос препроцессора под названием NULL (определен в заголовке ). Этот макрос был унаследован от C, где он обычно используется для обозначения нулевого указателя.
Значение NULL определяется реализацией, но обычно определяется как целочисленная константа 0. Примечание. Начиная с C++11, NULL можно определить как nullptr (что мы обсудим позже).
Лучшая практика
Опасности использования 0 (или NULL ) для нулевых указателей
nullptr в C++11
Начиная с C++11, когда нам нужен нулевой указатель, следует отдавать предпочтение ему, а не нулю:
Для продвинутых читателей
Функция со списком других параметров является новой функцией, даже если функция с таким же именем существует. Мы рассмотрели это в уроке «8.9 – Перегрузка функций».
Лучшая практика
Используйте nullptr для инициализации указателей нулевым значением.
std::nullptr_t
Возможно, вам никогда не понадобится это использовать, но на всякий случай знать полезно.
Десять возможностей C++11, которые должен использовать каждый C++ разработчик
В данной статье рассматривается ряд возможностей С++11, которые все разработчики должны знать и использовать. Существует много новых дополнений к языку и стандартной библиотеке, эта статья лишь поверхностно охватывает часть из них. Однако, я полагаю, что некоторые из этих новых функций должны стать обыденными для всех разработчиков С++. Подобных статей наверное существует много, в этой я предприму попытку составить список возможностей, которые должны войти в повседневное использование.
#1 — auto
До С++11, ключевое слово auto использовалось как спецификатор хранения переменной (как, например, register, static, extern ). В С++11 auto позволяет не указывать тип переменной явно, говоря компилятору, чтобы он сам определил фактический тип переменной, на основе типа инициализируемого значения. Это может использоваться при объявлении переменных в различных областях видимости, как, например, пространство имен, блоки, инициализация в цикле и т.п.
#2 — nullptr
#3 — range-based циклы
Это полезно, когда вы просто хотите получить элементы массива/контейнера или сделать с ними что-то, не заботясь об индексах, итераторах или кол-ве элементов.
#4 — override и final
Мне всегда не нравились виртуальные функции в С++. Ключевое слово virtual опционально и поэтому немного затрудняло чтение кода, заставляя вечно возвращаться в вершину иерархии наследования, чтобы посмотреть объявлен ли виртуальным тот или иной метод. Я всегда использовал этой ключевое слово так же и в производных классах (и поощрял людей, кто так делал), чтобы код был понятнее. Тем не менее, есть ошибки, которые могут все таки возникнуть. Возьмем следующий пример:
Вот другая возможная ошибка: параметры одни и те же, но в базовом классе метод константный, а в производном — нет.
Теперь это вызовет ошибку при компиляции (точно так же, если бы вы использовали override во втором примере):
#5 — строго-типизированный enum
У «традиционных» перечислений в С++ есть некоторые недостатки: они экспортируют свои значения в окружающую область видимости (что может привести к конфликту имен), они неявно преобразовываются в целый тип и не могут иметь определенный пользователем тип.
#6 — интеллектуальные указатели
Первое объявление эквивалентно следующему:
make_shared — это функция, имеющая преимущество при выделении памяти для совместно используемого объекта и интеллектуального указателя с единственным выделением, в отличие от явного получения shared_ptr через конструктор, где требуется, по крайней мере, два выделения. Из-за этого может произойти утечка памяти. В следующем примере как раз это демонстрируется, утечка может произойти в случае, если seed() бросит исключение.
#7 — лямбды
#8 — non-member begin() и end()
Давайте возьмем, например, предыдущий пример, где я выводил вектор и затем искал первый нечетный элемент. Если std::vector заменить С-подобным массивом, то код будет выглядеть так:
С begin() и end() его можно переписать следующим образом:
#9 — static_assert и классы свойств
static_assert проверяет утверждение во время компиляции. Если утверждение — истина, то ничего не происходит. Если — ложь, то компилятор выводит указанное сообщение об ошибке.
Однако, при компиляции не возникнет ошибки, если написать следующее:
#10 — семантика перемещения
Это — еще одна важная тема, затронутая в С++11. На эту тему можно написать несколько статей, а не абзацев, поэтому я не буду сильно углубляться.
C++11 ввел понятие rvalue ссылок (указанных с &&), чтобы отличать ссылка на lvalue (объект, у которого есть имя) и rvalue (объект, у которого нет имени). Семантика перемещения позволяет изменять rvalues (ранее они считались неизменными и не отличались от типов const T&).
Класс/структура раньше имели некоторые неявные функции-члены: конструктор по умолчанию (если другой конструктор не определен), конструктор копирования и деструктор. Конструктор копирования выполняет поразрядное копирование переменных. Это означает, что если у вас есть класс с указателями на какие-то объекты, то конструктор копирования скопирует указатели, а не объекты, на которые они указывают. Если вы хотите получить в копии именно объекты, а не лишь указатели на них, вы должны это явно описать в конструкторе копирования.
Конструктор перемещения и оператор присваивания перемещения — эти две специальные функции принимают параметр T&&, который является rvalue. Фактически, они могут изменять объект.
Следующий пример показывает фиктивную реализацию буфера. Буфер идентифицируется именем, имеет указатель (обернутый в std::unique_ptr ) на массив элементов типа Т и переменную, содержащую размер массива.
Конструктор копирования по умолчанию и оператор присваивания копии должны быть вам знакомы. Новое в С++11 — это конструктор перемещения и оператор присваивания перемещения, Если вы выполните этот код, то увидите, что когда создается b4 — вызывается конструктор перемещения. Кроме того, когда b1 присваивается значение — вызывается оператор присваивания перемещения. Причина — значение, возвращаемое функцией getBuffer() — rvalue.
What exactly is nullptr?
Still, I am not getting how nullptr works. For example, Wikipedia article says:
C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type. It is not implicitly convertible or comparable to integral types, except for bool.
How is it a keyword and an instance of a type?
14 Answers 14
How is it a keyword and an instance of a type?
Why nullptr in C++11? What is it? Why is NULL not sufficient?
C++ expert Alex Allain says it perfectly here (my emphasis added in bold):
. imagine you have the following two function declarations:
Although it looks like the second function will be called—you are, after all, passing in what seems to be a pointer—it’s really the first function that will be called! The trouble is that because NULL is 0, and 0 is an integer, the first version of func will be called instead. This is the kind of thing that, yes, doesn’t happen all the time, but when it does happen, is extremely frustrating and confusing. If you didn’t know the details of what is going on, it might well look like a compiler bug. A language feature that looks like a compiler bug is, well, not something you want.
Enter nullptr. In C++11, nullptr is a new keyword that can (and should!) be used to represent NULL pointers; in other words, wherever you were writing NULL before, you should use nullptr instead. It’s no more clear to you, the programmer, (everyone knows what NULL means), but it’s more explicit to the compiler, which will no longer see 0s everywhere being used to have special meaning when used as a pointer.
Allain ends his article with:
Regardless of all this—the rule of thumb for C++11 is simply to start using nullptr whenever you would have otherwise used NULL in the past.
nullptr (C++/CLI и C++/CX)
Используйте nullptr с управляемым или машинным кодом. Компилятор выводит соответствующие, но различные инструкции для управляемых и машинных значений пустых указателей. Дополнительные сведения об использовании версии этого ключевого слова в соответствии со стандартом ISO C++ см. в разделе nullptr.
nullptr ключевое слово эквивалентно значению nullptr в Visual Basic и null в C#.
Использование
nullptr Ключевое слово можно использовать в любом месте, где может использоваться маркер, собственный указатель или аргумент функции.
nullptr Ключевое слово не является типом и не поддерживается для использования с:
throw nullptr (однако throw (Object^)nullptr; будет работать)
nullptr Ключевое слово можно использовать при инициализации следующих типов указателей:
дескриптора среды выполнения Windows;
управляемого внутреннего указателя.
nullptr Ключевое слово можно использовать для проверки, имеет ли ссылка указателя или обработчика значение null перед использованием ссылки.
Вызовы функций для языков, использующих значения пустых указателей для проверки ошибок, должны правильно интерпретироваться.
Пример: nullptr ключевое слово
В следующем примере кода показано, что nullptr ключевое слово можно использовать везде, где можно использовать обработчик, собственный указатель или аргумент функции. В примере показано, что nullptr ключевое слово можно использовать для проверки ссылки перед ее использованием.
Пример. Использование nullptr и нулевое взаимозаменяемость
В следующем примере кода показано, что nullptr и ноль могут использоваться в собственных указателях в качестве взаимозаменяемых.
Пример: интерпретировать nullptr как маркер
В следующем примере кода показано, что nullptr интерпретируется как Handle в любой тип или собственный указатель на любой тип. В случае перегрузки функции с дескрипторами различных типов создается ошибка неоднозначности. Необходимо nullptr явно привести к типу.
Пример: CAST nullptr
В следующем примере кода показано, что приведение nullptr разрешено и возвращает указатель или обработчик для типа приведения, содержащего nullptr значение.
Пример. Передача nullptr в качестве параметра функции
В следующем примере кода показано, что nullptr можно использовать в качестве параметра функции.