Чем отличается null от nullptr
Перейти к содержимому

Чем отличается null от nullptr

  • автор:

nullptr (C++/CLI и C++/CX)

Ключевое слово nullptr представляет значение указателя NULL. Значение пустого указателя показывает, что тип дескриптора объекта, внутреннего указателя или собственного указателя не указывает на объект.

Используется nullptr с управляемым или машинным кодом. Компилятор выводит соответствующие, но различные инструкции для управляемых и машинных значений пустых указателей. Дополнительные сведения об использовании версии этого ключевого слова в соответствии со стандартом ISO C++ см. в разделе nullptr.

__nullptr ключевое слово — это ключевое слово, относящуюся к корпорации Майкрософт, которая имеет то же значение, что nullptr и код, но применяется только к машинному коду. Если вы используете nullptr собственный код C/C++, а затем компилируете с параметром компилятора /clr , компилятор не может определить, указывает ли nullptr собственное или управляемое значение указателя NULL. Чтобы сделать намерение понятным компилятору, используйте nullptr для указания управляемого значения или __nullptr для указания собственного значения.

Ключевое слово nullptr эквивалентен Nothing в Visual Basic и null в C#.

Использование

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

Ключевое слово nullptr не является типом и не поддерживается для использования:

  • sizeof
  • typeid
  • throw nullptr (однако throw (Object^)nullptr; будет работать)

Ключевое слово nullptr можно использовать в инициализации следующих типов указателей:

  • собственного указателя;
  • дескриптора среды выполнения Windows;
  • управляемого дескриптора;
  • управляемого внутреннего указателя.

nullptr Ключевое слово можно использовать для проверки, имеет ли указатель или дескриптор null перед использованием ссылки.

Вызовы функций для языков, использующих значения пустых указателей для проверки ошибок, должны правильно интерпретироваться.

Невозможно инициализировать дескриптор до нуля; можно использовать только nullptr . При присвоении константы 0 дескриптору объекта создаются упакованный тип Int32 и приведение к типу Object^ .

Пример: nullptr ключевое слово

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

// mcpp_nullptr.cpp // compile with: /clr value class V <>; ref class G <>; void f(System::Object ^) <> int main() < // Native pointer. int *pN = nullptr; // Managed handle. G ^pG = nullptr; V ^pV1 = nullptr; // Managed interior pointer. interior_ptrpV2 = nullptr; // Reference checking before using a pointer. if (pN == nullptr) <> if (pG == nullptr) <> if (pV1 == nullptr) <> if (pV2 == nullptr) <> // nullptr can be used as a function argument. f(nullptr); // calls f(System::Object ^) > 

Пример. Использование и ноль nullptr взаимозаменяемого использования

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

// mcpp_nullptr_1.cpp // compile with: /clr class MyClass < public: int i; >; int main()
pMyClass == nullptr pMyClass == 0 pMyClass == nullptr pMyClass == 0 

Пример. Интерпретация nullptr как дескриптор

В следующем примере кода показано, что nullptr интерпретируется как дескриптор любого типа или собственного указателя на любой тип. В случае перегрузки функции с дескрипторами различных типов создается ошибка неоднозначности. Необходимо nullptr явно привести к типу.

// mcpp_nullptr_2.cpp // compile with: /clr /LD void f(int *)<> void f(int ^)<> void f_null() < f(nullptr); // C2668 // try one of the following lines instead f((int *) nullptr); f((int ^) nullptr); >

Пример: Приведение nullptr

В следующем примере кода показано, что приведение разрешено и возвращает указатель или дескриптор типа приведения nullptr , содержащего nullptr значение.

// mcpp_nullptr_3.cpp // compile with: /clr /LD using namespace System; template void f(T) <> // C2036 cannot deduce template type because nullptr can be any type int main() < f((Object ^) nullptr); // T = Object^, call f(Object ^) // Delete the following line to resolve. f(nullptr); f(0); // T = int, call f(int) >

Пример. Передача nullptr в качестве параметра функции

В следующем примере кода показано, что nullptr можно использовать в качестве параметра функции.

// mcpp_nullptr_4.cpp // compile with: /clr using namespace System; void f(Object ^ x) < Console::WriteLine("test"); >int main()
test 

Пример. Инициализация по умолчанию

В следующем примере кода показано, что при объявлении дескрипторов и не явной инициализации они инициализированы nullptr по умолчанию.

// mcpp_nullptr_5.cpp // compile with: /clr using namespace System; ref class MyClass < public: void Test() < MyClass ^pMyClass; // gc type if (pMyClass == nullptr) Console::WriteLine("NULL"); >>; int main() < MyClass ^ x = gcnew MyClass(); x ->Test(); > 
NULL 

Пример. Назначение собственного указателя nullptr

В следующем примере кода показано, что nullptr при компиляции с помощью собственного указателя /clr можно назначить указатель.

// mcpp_nullptr_6.cpp // compile with: /clr int main()

Требования

Параметр компилятора: необязателен; поддерживается всеми параметрами создания кода, включая /ZW и /clr .

NULL == nullptr в C++11?

не совcем. NULL большинством компиляторов с легкостью трактуется как 0 (на самом деле это обычно define). Но нет 100 гарантии, что это так. А вот nullptr — это известная для компилятора константа и компилятор знает, что это такое.

6 дек 2013 в 13:29

@KoVadim, можно сказать, что надежнее будет инициализировать указатели nullptr, для дальнейшей проверки на корректность, нежели NULL?

6 дек 2013 в 13:58

nullptr как раз специально ввели, что бы решить часть неоднозначных ситуаций с NULL. Это все лучше утрясется в голове, если понимать, то компилятор не видет NULL, он видит обычно вместо него 0 (препроцессор постарался). А вот nullptr виден. И компилятор может сделать анализ.

6 дек 2013 в 14:43

@SoloMio, не совсем. Везде где идет речь про указатели НУЖНО использовать null_ptr. Это гарантия того, что компилятор попробует застраховать программиста от ошибки.

c++ Null vs nullptr

Добрый день, вчера пытался разобраться в чем преимущество (конкретно, а не в виде абстрактных понятий типа ООП и прочая эзотерика) nullptr против NULL. Ничего внятного (для простых инженеров, а не всяких там страуструпов) не нашел, кроме синтетического примера

void foo(int *) < coutvoid foo(int) < coutfoo(NULL); foo(nullptr); 
foo(int) foo(int *) 

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

da17 ★
28.01.19 13:25:53 MSK

Но этого что-то мало и вроде я такое раз в год вызываю

Так можно про многие правила из стандарта сказать, типа я это почти не использую, а потому не нужно.

seiken ★★★★★
( 28.01.19 13:44:42 MSK )
Ответ на: комментарий от seiken 28.01.19 13:44:42 MSK

Так из-за этого и спрашиваю, где это используется?

da17 ★
( 28.01.19 13:51:37 MSK ) автор топика

у меня твой пример не компилируется.

 error: call of overloaded ‘foo(NULL)’ is ambiguous

conalex ★★★
( 28.01.19 13:57:09 MSK )
Ответ на: комментарий от conalex 28.01.19 13:57:09 MSK

MSVC 2013 собирал, там норм прошло

da17 ★
( 28.01.19 14:16:43 MSK ) автор топика
Ответ на: комментарий от da17 28.01.19 13:51:37 MSK

NULL это просто 0, ещё и определённый макросом, т.е. компилятор получит просто 0 в этом куске кода, некоторые конструкции аля auto не поймут что именно ты хотел использовать число или указатель

sparks ★★★
( 28.01.19 14:33:13 MSK )

Effective Modern C++ Майерса.
Item 8: Prefer nullptr to 0 and NULL.

Показано развитие приведённого тобою примера для случая когда такие перегрузки за шаблонами скрыты.

mkam ★
( 28.01.19 14:36:12 MSK )

nullptr нельзя по ошибке присвоить переменной, не являющейся указателем, с NULL такое скомпилируется и может потом привести к многочасовой отладке

annulen ★★★★★
( 28.01.19 14:40:07 MSK )
Ответ на: комментарий от annulen 28.01.19 14:40:07 MSK
da17 ★
( 28.01.19 15:08:26 MSK ) автор топика

На будущее: когда тебе говорят что NULL это легаси и нужно пользоваться nullptr, тебе нужно просто это сделать а не задаваться бесполезными вопросами.

Если же тебе неймётся, все ответы есть на cppreference. NULL - это implementation-defined макрос который может в зависимости от реализации раскрываться в 0 или nullptr, поэтому вопрос сводится к тому почему нельзя использовать 0 (или, что эквивалентно, макрос который может в него раскрыться). Потому что это нарушает типобезопасность - 0 можно передать в функцию принимающую int, или сравнить с int’ом. Если ты сравниваешь NULL с int’ом, или передаёшь в качестве int’а - это явная ошибка, но в этом случае компилятор её не отловит. У nullptr таких проблем нет. Кроме того, он может участвовать в перегрузках (https://en.cppreference.com/w/cpp/types/nullptr_t).

slovazap ★★★★★
( 28.01.19 15:09:25 MSK )
Ответ на: комментарий от da17 28.01.19 15:08:26 MSK

void f(int a); f(nullptr); // error 

annulen ★★★★★
( 28.01.19 15:14:36 MSK )
Ответ на: комментарий от slovazap 28.01.19 15:09:25 MSK

сравниваю NULL с int

#include #include class Keker< >; int main()

Компилятор ругается In function 'int main()': 12:16: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

da17 ★
( 28.01.19 15:16:36 MSK ) автор топика

Дальше не читал

Gvidon ★★★★
( 28.01.19 15:19:10 MSK )
Ответ на: комментарий от Gvidon 28.01.19 15:19:10 MSK

Я прочитал пример https://en.cppreference.com/w/cpp/types/nullptr_t т.е. если я все правильно понял, nullptr помогает явно указать, что должна вызываться ф-ия принимающая указатель и если у программиста функция, принимающая foo(int), а он где-то в дебрях кода передает ей нулевой указатель путем foo(NULL), то возможно он ошибся и nullptr от таких косяков уберегает, т.е. если даже программист забудет, чего принимает ф-ия, компилятор его поправит при nullptr, чего не будет при NULL?

da17 ★
( 28.01.19 15:30:21 MSK ) автор топика
Ответ на: комментарий от Gvidon 28.01.19 15:19:10 MSK

да я пошутил, а то иногда напишут вместо пояснения «НАРУШАЕТ ПРИНЦИПЫ ООП» и гадай, что оно там нарушает

da17 ★
( 28.01.19 15:32:18 MSK ) автор топика

История примерно такая:
1) В С++ запретили неявное приведение void* к любому другому указателю, что в С разрешено. Внезапно, отломался код

int* foo = NULL; 

т.к. NULL всегда определялся как (void*)0.
2) Не унывая, в С++ решили эту проблему переиспользованием константы 0, что привело к вот такой вот радости (примерно):

#ifdef __cplusplus #define NULL 0 #else #define NULL (void*)0 #endif 

Что, в свою очередь, начало весело стрелять при перегрузках и в шаблонах.
3) Компиляторы от такой весёлой жизни начали заводить свои нестандартные «нулевые указатели», чтобы с этим адом хоть как-то бороться. Например __null в gcc.
4) Пункт 3) узаконили в стандарте как nullptr

Всё это время сишники смотрят на плюсовиков как на стадо дебилов, пишут свой родной NULL и в ус не дуют.

Gvidon ★★★★
( 28.01.19 15:59:55 MSK )
Ответ на: комментарий от da17 28.01.19 15:16:36 MSK

И что вы хотели сказать этим примером? К NULL vs. nullptr он вообще никакого отношения не имеет.

slovazap ★★★★★
( 28.01.19 16:32:37 MSK )

В чистом Си у тебя ведь перегрузки функций нет? Вот там это в ногу не выстрелит. А в костылях выстрелит и будет неприятно.

Вот и пиши nullptr , чтобы избежать двусмысленности.

Deleted
( 28.01.19 16:41:55 MSK )
Ответ на: комментарий от da17 28.01.19 15:08:26 MSK

Например такой: #include

int main() < char str[] = "hello"; char* p = str; /* что-то делаем со строкой */ p = 0; >

То есть мы работаем со строкой, теперь захотели ограничить строку на текущем символе, и вместо

*p = '\0'; 

написали просто

p = 0; 

Какой-то пример с массивом строк и присваиванием нуля, вместо '\0', был в одном из разборов PVS-studio какого-то опенсурс проекта, так что несмотря на то что пример искусственный, что-то подобное есть и в реальных проектах.

Но в gcc/clang есть полезное предупреждение

-Wzero-as-null-pointer-constant 

Что использовать с указателями? 0, NULL, nullptr?

Author24 — интернет-сервис помощи студентам

NULL в WinDef.h описан как #define NULL 0. То есть в случае использования как с указателями, так и другими переменными разницы 0. Про nullptr только час назад узнал, даёт ли он какие-либо реальные преимущества?

Но, вообщем-то, главный вопрос: что использовать?

Лучшие ответы ( 2 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Разница между NULL, nullptr и 0
Не очень давно занимаюсь программированием. Хотелось бы узнать в чём разница между NULL, nullptr и.

NULL с указателями
С понятием NULL столкнулся только что при изучении указателей. Поэтому еще не понимаю зачем он.

Стоит ли использовать null ?
Впервые сталкиваюсь с null. Вещь вроде бы полезная, помогает избавиться от мусора, но её не.

Оптимально ли использовать методы расширения для проверки на null?
Коллеги добрый день! Подскажите, совсем запамятовал.. Вот часто бывает необходимость проверить.

Эксперт С++

8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30

Я чисто для наглядности в коде использую NULL для инициализации указателей (для переменных 0 ).

Поидее для указателей придумали nullptr ( но он не так бросается в глаза как NULL.)

2554 / 1319 / 178
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
Самое банальное

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include #include void foo(const int&) { std::cout  "foo(const int&)"  std::endl; } void foo(const int*) { std::cout  "foo(const int*)"  std::endl; } int main() { foo(NULL); foo(nullptr); return 0; }

Регистрация: 06.07.2012
Сообщений: 88

Лучший ответ

Сообщение было отмечено как решение

Решение

Rengen, для обнуление указателя лучше использовать nullptr, т.к.:
"Причина введения nullptr в язык С++ заключается в устранение возможных недоразумений между литералом 0 как целочисленным значением и указателем. Двойное значение литерала 0 может вызывать проблемы при некоторых обстоятельствах. Литерал nullptr имеет тип std::nullptr_t, и его нельзя перепутать со значением другого типа. Он может быть неявно преобразован в любой ссылочный тип, но ни в один целочисленный тип, кроме типа bool." - Айвор Хортон, Visual C++ 2010, Глава 4 *примечание.

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

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