Возможности C++11: nullptr

Jun 14, 2013 17:22

Одним из нововведений С++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.

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

программирование, c++11, c++

Previous post Next post
Up