NULL
был перехвачен из C в C ++ и - до C ++ 11 - принял его значение C:
до C ++ 11: макрос NULL определяется реализациейконстанта нулевого указателя, которая может быть целочисленным выражением-константой rvalue целочисленного типа с нулевым значением.
C ++ 11 затем ввела выделенный литерал нулевого указателя nullptr
типа std::nullptr_t
.Но - вероятно, для обратной совместимости - макрос NULL
не был удален;его определение было немного смягчено, поскольку компиляторы теперь могут определять его как целочисленный или как тип указателя:
C ++ 11 и далее: целочисленный литерал со значением ноль или значение типа std:: nullptr_t
Если вы используете NULL
, то вы получите поведение, определяемое реализацией в разрешении перегрузки.Рассмотрим, например, следующий код с компилятором, который использует целочисленную версию NULL
-macro.Тогда вызов с использованием NULL
в качестве параметра, передаваемого в функцию, может привести к неоднозначности:
struct SomeOverload {
SomeOverload(int x) {
cout << "taking int param: " << x << endl;
}
SomeOverload(void* x) {
cout << "taking void* param: " << x << endl;
}
};
int main() {
int someVal = 10;
SomeOverload a(0);
SomeOverload b(&someVal);
// SomeOverload c(NULL); // Call to constructor is ambiuous
SomeOverload d(nullptr);
}
Поэтому рекомендуется использовать nullptr
везде, где вы хотите выразить тип указателя.
И не используйте __null
, так как это непереносимая константа для конкретного компилятора;nullptr
, напротив, идеально переносимый.