is_реклам:

пошук, категорії та ін. показати ▼

nullptr, NULL та 0 — що використовувати?

nullptr, NULL та 0 — що використовувати?
автор опубліковано


NULL — макрос нульового вказівника. При зверненні до нього, макрос замінюється на нульовий постійний вказівник. Використовується для позначення того, що вказівник не вказує ні на який об'єкт.

Нерідко в програмах на С++ можна побачити використання 0 замість NULL, це навіть рекомендують, оскільки числове значення на відміну від макросу не може бути випадково перевизначене. Хоча, деякі програмісти вважають, що використання значення 0 замість NULL погіршує читабельність коду. Насправді ж, NULL як макрос залишився для сумісності з мовою С.

Отже, яка різниця?

Почнемо з класичної мови С. В ній макрос NULL визначений наступним чином

#define NULL ((void *)0)

Тобто NULL визначено як нульовий вказівник. Мова С дозволяє порівнювати вказівник загального типу void* з вказівником будь-якого іншого типу.

Більш строга мова С++ забороняє порівняння різних вказівників. Константа NULL визначена як звичайний нуль:

#define NULL 0

В мові С гарантується, що нульовий вказівник не дорівнює вказівнику на будь-який об'єкт (в широкому розумінні слова, певні дані) або функцію.

В С++ використання NULL може призвести до помилок, оскільки опосердковано може бути включено заголовок, де стандартне визначення С++ для NULL перекривається (і він буде визначений як (void*)0, а не 0). У випадку, якщо NULL визначено як (void*)0 код

int (ClassName::*pf)() = NULL;

призведе до помилки компіляції.

Але, навіть, якщо визначення

#define NULL 0

в С++ ніяк не перекривалося, чи завжди NULL буде поводити себе як потрібно програмісту?

Знову ні! Припустимо, що є перезавантажена функція

void func(int x); 
void func(float* ptr);

і програміст хоче викликати другий варіант (з float*), передавши нульовий вказівник

func(NULL); 

Але насправді викличеться перший варіант (з int).

Для усунення недоліків, в новий стандарт мови С++11 додано ключове слово nullptr, що однозначно ідентифікує нульовий вказівник.
Тепер вже при виклику

func(nullptr); 

спрацює другий варіант функції (з float*), як і очікується. Неявно nullptr конвертується тільки в будь-який тип вказівника (включаючи вказівники на члени класу) і в bool (як false). Але ніколи в int!

Ключове слово nullptr має свій власний тип, визначений наступним чином

typedef decltype(nullptr) nullptr_t;

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

Так що, якщо Ваш компілятор підтримує nullptr, починайте його використовувати.

схоже за тегами

Залишити коментар:

Яндекс цитирования UA TOP Bloggers