Одним из нововведений С++11 является ключевое слово nullptr, предназначенное для обозначения нулевого указателя.
Традиционно для того, чтобы обнулить указатель, ему присваивали значение 0, либо использовали вариант с макроопределением NULL, доставшийся в наследство от языка C:
ptr *a = 0;
ptr *b = NULL;
Вынесем за скобки то обстоятельство, что макрос как таковой не должен вызывать доверия, ведь само по себе использование целочисленного литерала способно преподносить неприятные сюрпризы в неожиданных местах, например при вызове перегруженных функций.
Рассмотрим следующий код:
#include
class foo {
public:
void bar ( const int num) { std::cout << "int version called\n";}
void bar ( const foo *ptr) { std::cout << "ptr version called\n";}
};
int main () {
foo *f = new foo;
f -> bar( 0);
f -> bar( NULL);
delete f;
std::cin.get();
return 0;
}
В результате получим:
int version called
int version called
То есть оба раза вызван первый вариант метода bar. А если всё же требуется второй, придётся позаботиться о преобразовании типа при вызове:
f -> bar( static_cast
(0));
f -> bar( static_cast(NULL))
Отметим, что в данном случае макрос NULL был определен как #define NULL 0, но если бы это было не так, результат был бы менее предсказуем.
Данная проблема актуальна и при использовании шаблонов. Например, следующая программа просто не скомпилируется:
#include
template< typename F, typename P>
void doSmth( F func, P param) {
func( param);
}
void someFunc( void*) {
std::cout << "someFunc called\n";
}
int main () {
someFunc( 0); // ok
someFunc( NULL); // ok
doSmth( someFunc, nullptr); // fine
doSmth( someFunc, NULL); // error C2664 cannot convert parameter
doSmth( someFunc, 0); // the same error
std::cin.get();
return 0;
}
Ключевое слово nullptr лишено этих недостатков, потому что имеет свой собственный тип std::nullptr_t.
Неявно преобразовывается к нулевому указателю любого типа и к bool, но не к целочисленным типам:
foo *f = 0;
if ( f == nullptr)
std::cout << "nullptr" << std::endl;
foo *ff = nullptr;
if ( !ff)
std::cout << "nullptr" << std::endl;
int fail = nullptr; // error C2440
Таким образом, использование nullptr в ваших новых проектах способно существенно облегчить жизнь, благо поддержка этой фичи появилась ещё в MS Visual C++ 2010.
Возможно, в будущем мы поговорим и о других полезных особенностях нового стандарта.