nullptr_t是默认的可构造类型吗

Is nullptr_t a default constructible type?

本文关键字:类型 默认 nullptr      更新时间:2023-10-16

我无法从C++11标准中判断nullptr_t是否有默认构造函数。换句话说,以下内容有效吗?:

nullptr_t n; 

GCC和VC++允许上面的代码,但clang不允许。我在Standard中找不到任何指定它没有默认构造函数的内容,我能找到的表明它应该有默认构造函数。这对我来说很重要,因为我正在为旧的编译器支持编写nullptr的基本后备实现,需要知道是否需要给它一个默认构造函数。

标准说明

标准规定(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的值未定义。正如Johannes Schaub正确指出的那样,这与Clang的最新版本很好地结合在一起
  • 值初始化(nullptr_t n = nullptr_t();),将n初始化为0

这种行为与例如int相同,因此nullptr_t绝对是默认可构造的。这里有趣的问题是:nullptr_t具有未定义的值意味着什么?在一天结束时,nullptr_t只有一个有意义的可能值,即nullptr。此外,类型本身仅通过nullptr文本的语义来定义。这些语义仍然适用于单元化的值吗?

为什么这个问题在实践中无关紧要

您不希望声明nullptr_t类型的新变量。该类型唯一有意义的语义已经通过nullptr文本表达,因此无论何时使用nullptr_t类型的自定义变量,都可以使用nullptr

实践中重要的是什么

唯一的例外是,您可以使用类型为nullptr_t的非类型模板参数。对于这种情况,了解哪些值可以转换为nullptr_t是有用的,如4.10:所述

空指针常量是整数类型的整数常量表达式(5.19)prvalue,其计算结果为零或std::nullptr_t类型的prvalue。[…]整型的空指针常量可以转换为std::nullptr_t类型的prvalue。

这基本上正是你所期望的:你可以写

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都做到了这一点。

虽然nullptr是语言本身的新添加,但std::nullptr_t只是未命名类型的别名,cstddef中声明的别名如下:

typedef decltype(nullptr) nullptr_t;

虽然nullptr_t是一个typedef,而不是语言关键字,没有被列为基本类型,但它被指定为基本类型(例如,不是指针类型或类类型)。因此,它没有默认的构造函数,但您仍然可以像以前那样声明变量。您的变量没有初始化,我想知道它的用途是什么,以及您从clang中到底得到了什么错误消息。

另请参见此处。