您无法声明void
变量:
void fn() {
void a; // ill-formed
}
然而这编译:
void fn() {
void(); // a void object?
}
void()
是什么意思?它有用吗?为什么void a;
格式不正确,而void()
好吗?
void fn() {
void a = void(); // ill-formed
}
答案 0 :(得分:5)
声明
void();
创建一个空值,然后丢弃它。 (除了丢弃它或返回它之外,你实际上无法使用空值。)
standard†在5.2.3 [expr.type.conv
中说明表达式T(),其中T是非数组完整对象的simple-type-specifier或typename-specifier type或(可能是cv-qualified)void类型,创建一个指定类型的prvalue,其值为 通过值初始化(8.5)生成类型为T的对象;没有为void()case
进行初始化
请注意,它明确地提到void()
是合法的。
†我的链接是N4296,这是C ++ 14之前的最后一次公共委员会草案,但是这个标准的各个版本在这里没有变化。
修改强>
有用吗?明白这样吗?不,我看不到它的用途。然而,它 在模板函数中很有用,它们有时会执行以下操作:
template <typename T>
T foo() {
if (prepare_for_for()) {
return do_foo();
} else {
return T();
}
}
即使是T
== void
。
答案 1 :(得分:3)
语法void()
是用功能表示法编写的明显类型转换(见5.2.3)。
请注意,即使在“经典”C(C89 / 90)中,也已允许对void
进行显式转换。当然,在C中,必须使用“经典”C风格的演员表示法并提供一个参数。任何表达式都可以转换为C中的void
,包括已经void
的表达式。此功能在C ++中未更改地迁移到显式类型转换的强制转换符号(它由其功能的static_cast
分支处理,即您可以static_cast
到void
in C ++)。
考虑到上述情况,替代C ++强制语法 - 功能表示法也始终支持转换为void
并不奇怪。一旦你理解了这一点,毫不奇怪它被扩展到支持“无论证”版本 - void()
。
这在C ++中的用处将包括诸如泛型函数
之类的上下文template <typename T>
T foo() {
...;
return T(); // remains valid even when `T == void`
}
请注意,在C ++中,从void
函数返回void
伪值是完全合法的。创建此类void()
伪值的能力消除了为上述函数编写专用void
特化的需要。
作为旁注,void()
仅代表显式类型转换,前提是上下文强制将其解释为表达式,如示例所示。当上下文调用类型名称(例如int foo(void())
或using T = void();
)时,它实际上声明了一个返回void
并且不带参数的无名函数。