Nullptr c что это

от admin

Что такое nullptr в C++?

Ответ на вопрос Что такое nullptr в C++? было бы проще простого для опытных глаз C++ и для тех, кто знает о современном C++, то есть ключевом слове. Но nullptr — это больше, чем просто ключевое слово в C++, и чтобы объяснить это, я написал эту статью. Но прежде чем перейти к этому, мы увидим проблемы с NULL , а затем мы погрузимся в простую реализацию nullptr и некоторые варианты использования nullptr .

Примечание. Эта статья более или менее похожа на ту, что вы можете найти здесь, здесь и в предложении nullptr (N2431), но в более организованном виде. & упрощенный способ.

Зачем нам нульптр?

Чтобы различать целое число 0 (ноль), т. е. NULL, и фактический нуль указателя типа.

nullptr против NULL

  • NULL — это 0 (ноль), т.е. целочисленная константа ноль с приведением типов в стиле C к void* , а nullptr — это prvalue типа nullptr_t , который является целочисленным литераломравно нулю.
  • Для тех из вас, кто считает, что NULL одно и то же, то есть (void*)0 в C и C++. Я хотел бы уточнить, что нет, это не так:
  • C++ требует, чтобы макрос NULL был определен как целочисленное константное выражение, имеющее значение 0 . Таким образом, в отличие от C, NULL не может быть определено как (void *)0 в стандартной библиотеке C++.

Проблемы с NULL

1️⃣ Неявное преобразование

2️⃣ Неоднозначность вызова функции

Компиляция выдает следующую ошибку:

3️⃣ Перегрузка конструктора

  • В таких случаях вам нужно явное приведение (например, String s((char*)0)) .

Реализация незамысловатого nullptr

  • nullptr — тонкий пример идиомы Return Type Resolver для автоматического вывода нулевого указателя правильного типа в зависимости от типа экземпляра, которому он назначается.
  • Рассмотрим следующую простейшую и бесхитростную реализацию nullptr :
  • Если вышеприведенный код кажется вам странным и странным (хотя так и должно быть), то я бы посоветовал вам прочитать мою предыдущую статью о продвинутых концепциях C++. Волшебство здесь заключается в шаблонном операторе преобразования.
  • Если вам интересен более авторитетный источник, то вот конкретная реализация nullptr из заголовка LLVM.

Варианты использования nullptr

  • Как показано в приведенном выше примере, когда nullptr присваивается целочисленному указателю, создается экземпляр типа int шаблонной функции преобразования. То же самое относится и к указателям на методы.
  • Таким образом, используя функциональность шаблона, мы фактически создаем соответствующий тип нулевого указателя каждый раз, когда мы это делаем, назначение нового типа.
  • Поскольку nullptr — это целочисленный литерал с нулевым значением, вы не сможете использовать его адрес, что мы и сделали, удалив оператор &.

1️⃣ Ясность вызова функции с помощью nullptr

  • Теперь func( int* ) будет вызываться, поскольку nullptr будет неявно выводиться из int* .

2️⃣ Приведение типов по nullptr_t

  • Приведение nullptr_t к целочисленному типу требует reinterpret_cast и имеет ту же семантику, что и приведение (void*)0 к целочисленному типу.
  • Приведение nullptr_t к целочисленному типу выполняется до тех пор, пока целевой тип достаточно велик. Учти это:
  • reinterpret_cast не может преобразовать nullptr_t в любой тип указателя. Вместо этого используйте static_cast .
  • nullptr неявно преобразуется в любой тип указателя, поэтому явное преобразование с static_cast допустимо только.

3️⃣ nullptr_t сопоставим

Из Википедии: — …константа нулевого указателя: nullptr . Это тип nullptr_t , который неявно преобразуется и сравним с любым типом указателя или типа указателя на член.
– Он не может быть неявно преобразован или сравним с целочисленными типами, за исключением bool .

4️⃣ Шаблон-аргумент имеет тип std::nullptr_t

  • Как обсуждалось ранее, Return Type Resolver требуется правопреемник для вывода типа.

5️⃣ Преобразование в bool из nullptr_t

Из cppreference:
— в контексте прямой инициализации объект bool может быть инициализирован значением prvalue типа std::nullptr_t , включая nullptr . Полученное значение является ложным. Однако это не считается неявным преобразованием.

  • Преобразование разрешено только для прямой инициализации, но не для копирования-инициализации, включая случай передачи аргумента в функцию по значению. например

6️⃣ Разное

Резюме по часто задаваемым вопросам

Когда был представлен nullptr ?

Является ли nullptr ключевым словом или экземпляром типа std::nullptr_t ?

И true , и false являются ключевыми словами и литералами, поскольку они имеют тип ( bool ). nullptr — это литерал указателя типа std::nullptr_t , и это значение prvalue (то есть чистое rvalue, вы не можете получить его адрес, используя & ). «Для большего».

Каковы преимущества использования nullptr?

— Нет функции, вызывающей двусмысленность между наборами перегрузки.
— Вы можете выполнять специализацию шаблона с помощью nullptr_t .
— Код станет более безопасным, интуитивно понятным и выразительным. if (ptr == nullptr); , а не if (ptr == 0); .

Является ли NULL в C++ равным nullptr из C++11?

Нисколько. Следующая строка даже не компилируется:

Можно ли преобразовать nullptr в bool?

да. Но только при прямой инициализации. то есть bool is_false; . В противном случае необходимо использовать static_cast .

Как определяется nullptr ?

Это просто шаблонный оператор преобразования, известный как Return Type Resolver.

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

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

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

Помимо адресов памяти, есть еще одно значение, которое указатель может хранить: значение 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. Например:

Читать:
Какой scope будет учитывать cbam

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

Урок №80. Указатели

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

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

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

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

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

alt=»Avatar photo» width=»50″ height=»50″ />Юрий :

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

Каждая переменная или константа должна быть определенного типа.
Следовательно, у 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>.

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

What exactly nullptr is in C++?

The answer to “What exactly nullptr is in C++?” would be a piece of cake for experienced C++ eyes & for those who are aware of Modern C++ i.e. keyword. But nullptr is more than just a keyword in C++ & to explain that, I have written this article. But before jump-into it, we will see issues with NULL & then we'll dive into the unsophisticated implementation of nullptr & some use-cases of nullptr .

Note: This article is more or less the same thing which you can find here, here & in nullptr proposal(N2431) but in a bit organized & simplified way.

Why do we need nullptr?

To distinguish between an integer 0(zero) i.e. NULL & actual null of type pointer.

nullptr vs NULL

  • NULL is 0 (zero) i.e. integer constant zero with C-style typecast to void* , while nullptr is prvalue of type nullptr_t which is integer literalevaluates to zero.
  • For those of you who believe that NULL is same i.e. (void*)0 in C & C++. I would like to clarify that no it's not:
  • C++ requires that macro NULL to be defined as an integral constant expression having the value of 0 . So unlike in C, NULL cannot be defined as (void *)0 in the C++ standard library.

Issues with NULL

1️⃣ Implicit conversion

2️⃣ Function calling ambiguity

Compilation produces the following error:

3️⃣ Constructor overload

  • In such cases, you need explicit cast (i.e., String s((char*)0)) .

Implementation of unsophisticated nullptr

  • nullptr is a subtle example of Return Type Resolver idiom to automatically deduce a null pointer of the correct type depending upon the type of the instance it is assigning to.
  • Consider the following simplest & unsophisticated nullptr implementation:
  • If the above code seems strange & weird to you(although it should not), then I would suggest you go through my earlier article on advanced C++ concepts. The magic here is just the templatized conversion operator.
  • If you are into a more authoritative source, then, here is a concrete implementation of nullptr from LLVM header.

Use-cases of nullptr

  • As shown in the above example, when nullptr is being assigned to an integer pointer, a int type instantiation of the templatized conversion function is created. And same goes for method pointers too.
  • This way by leveraging template functionality, we are actually creating the appropriate type of null pointer every time we do, a new type assignment.
  • As nullptr is an integer literal with value zero, you can not able to use its address which we accomplished by deleting & operator.

1️⃣ Function calling clarity with nullptr

  • Now, func( int* ) will be called as nullptr will implicitly be deduced to int* .

2️⃣ Typecasting on nullptr_t

  • A cast of nullptr_t to an integral type needs a reinterpret_cast , and has the same semantics as a cast of (void*)0 to an integral type.
  • Casting nullptr_t to an integral type holds true as long as destination type is large enough. Consider this:
  • A reinterpret_cast cannot convert nullptr_t to any pointer type. Use static_cast instead.
  • nullptr is implicitly convertible to any pointer type so explicit conversion with static_cast is only valid.

3️⃣ nullptr_t is comparable

From Wikipedia: — …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 .

4️⃣ Template-argument is of type std::nullptr_t

  • As discussed earlier, Return Type Resolver needs an assignee to deduce the type.

5️⃣ Conversion to bool from nullptr_t

From cppreference :
— In the context of a
direct-initialization, a bool object may be initialized from a prvalue of type std::nullptr_t , including nullptr . The resulting value is false. However, this is not considered to be an implicit conversion.

  • The conversion is only allowed for direct-initialization, but not copy-intialization, which including the case for passing an argument to a function by value. e.g.

6️⃣ Misc

Summary by FAQs

When was nullptr introduced?

Is nullptr a keyword or an instance of a type std::nullptr_t ?

Both true and false are keywords & literals, as they have a type ( bool ). nullptr is a pointer literal of type std::nullptr_t , & it's a prvalue (i.e. pure rvalue, you cannot take the address of it using & ). For more.

What are the advantages of using nullptr?

— No function calling ambiguity between overload sets.
— You can do template specialization with nullptr_t .
— Code will become more safe, intuitive & expressive. if (ptr == nullptr); rather than if (ptr == 0); .

Is NULL in C++ equal to nullptr from C++11?

Not at all. The following line does not even compile:

Can I convert nullptr to bool?

Yes. But only if you direct-initialization. i.e. bool is_false; . Else need to use static_cast .

How is nullptr defined?

It’s just the templatized conversion operator known as Return Type Resolver.

nullptr, the pointer literal

The keyword nullptr denotes the pointer literal. It is a prvalue of type std::nullptr_t . There exist implicit conversions from nullptr to null pointer value of any pointer type and any pointer to member type. Similar conversions exist for any null pointer constant, which includes values of type std::nullptr_t as well as the macro NULL .

[edit] Example

Demonstrates that nullptr retains the meaning of null pointer constant even if it is no longer a literal.

Похожие статьи