Ответ 1
Что говорит стандарт
В стандарте говорится (18.2)
nullptr_t определяется следующим образом:
namespace std { typedef decltype(nullptr) nullptr_t; }
Тип, для которого nullptr_t является синонимом, имеет характеристики, описанные в п. 3.9.1 и 4.10.
Где 3.9.1 в основном говорит, что он должен иметь тот же размер, что и void*
, а 4.10 определяет правила преобразования для nullptr
.
Изменить: 3.9.9 также явно заявляет, что nullptr_t
является скалярным типом, что означает, что применяются ожидаемые правила инициализации для встроенных типов из 8.5:
- Инициализация по умолчанию (
nullptr_t n;
), которая оставляет значениеn
undefined. Как правильно указал Йоханнес Шауб, это прекрасно компилируется с новейшей версией Clang. - Инициализация значений (
nullptr_t n = nullptr_t();
), которая инициализирует n до 0.
Это поведение идентично, например, int
, поэтому nullptr_t
определенно по умолчанию.
Интересный вопрос здесь: что значит для nullptr_t
иметь значение undefined? В конце дня для nullptr_t
существует только одно значащее возможное значение, которое nullptr
. Более того, сам тип определяется только семантикой литерала nullptr
. Используются ли эти семантики для унифицированного значения?
Почему этот вопрос не имеет значения на практике
Вы не хотите объявлять новую переменную типа nullptr_t
. Единственная значимая семантика этого типа уже выражается через литерал nullptr
, поэтому всякий раз, когда вы будете использовать свою настраиваемую переменную типа nullptr_t
, вы можете просто использовать nullptr
.
Что имеет значение на практике
Единственное исключение из этого исходит из того факта, что вы можете брать параметры шаблона типа типа nullptr_t
. Для этого случая полезно знать, какие значения могут преобразовываться в nullptr_t
, что описано в 4.10:
Константа нулевого указателя является интегральным константным выражением (5.19) prvalue целочисленного типа, которое оценивается в 0 или prvalue типа
std::nullptr_t
. [...] Константа нулевого указателя интегрального типа может быть преобразована в prvalue типаstd::nullptr_t
.
Что в основном делает именно то, что вы ожидаете: вы можете написать
nullptr_t n = 0; // correct: 0 is special
но не
nullptr_t n = 42; // WRONG can't convert int to nullptr_t
Оба gcc 4.6 и Clang SVN получают это право.