16

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

nullptr_t n; 

GCC 和 VC++ 允许使用上述代码,但 clang 不允许。我在标准中找不到任何指定它没有默认构造函数的东西,而我能找到的表明它应该有。这对我很重要,因为我正在编写 nullptr 的基本回退实现以支持旧编译器,并且需要知道是否需要为其提供默认构造函数。

4

2 回答 2

17

标准是怎么说的

标准说(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。

此行为与 eg 相同int,因此nullptr_t绝对是可默认构造的。这里有趣的问题是:nullptr_t具有未定义的值意味着什么?归根结底,只有一个有意义的可能值nullptr_t,即nullptr。此外,类型本身仅通过nullptr文字的语义来定义。这些语义是否仍然适用于未初始化的值?

为什么这个问题在实践中并不重要

你不想声明一个新的 type 变量nullptr_t。该类型唯一有意义的语义已经通过nullptr字面量表达,因此无论何时使用自定义变量 type nullptr_t,都可以使用nullptr.

在实践中重要的是什么

唯一的例外是您可以采用 type 的非类型模板参数nullptr_t。对于这种情况,了解哪些值可以转换为 是很有用的nullptr_t,这在 4.10 中进行了描述:

空指针常量是整数类型的整数常量表达式 (5.19) 纯右值,其计算结果为零或类型的纯右值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 都做到了这一点。

于 2012-03-31T08:22:48.090 回答
1

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

typedef decltype(nullptr) nullptr_t;

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

另请参见此处

于 2012-03-31T08:51:04.337 回答