【问题标题】:How is "void()" useful?“void()”有什么用?
【发布时间】:2017-12-04 17:19:35
【问题描述】:

您不能声明void 变量:

void fn() {
    void a; // ill-formed
}

然而这个编译:

void fn() {
    void(); // a void object?
}

void() 是什么意思?它有什么用处?为什么void a; 格式不正确,而void() 正常?

void fn() {
    void a = void(); // ill-formed
}

【问题讨论】:

  • 基本上什么都没有或没有类型
  • @sara 你应该仔细看看这里的上下文。
  • 虽然void() 很奇怪,但它与您可以将表达式转换为void 的事实基本一致,如在语句(void)5; 中(有时这样做是为了明确表示返回值被忽略)。在任何一种情况下,表达式都会产生一个 void 值。您不能声明 void 类型的变量,因为它是不完整的类型。
  • @geza 对不完整类型的主要限制是“不应将对象定义为具有不完整类型。”这并不排除不完整类型的表达。您甚至可以取消引用指向不完整类型的指针(尽管它必须是指向对象类型的指针,因此不包括 void),并且只要在取消引用的对象上不发生左值到右值的转换,它就是合法的。跨度>

标签: c++ void variable-declaration


【解决方案1】:

声明

void();

创建一个 void 值,然后将其丢弃。 (除了丢弃或返回它之外,您实际上不能对 void 值做很多事情。)

standard† 在 5.2.3 [expr.type.conv

中说

表达式 T(),其中 T 是非数组完整对象的简单类型说明符或类型名称说明符 type 或(可能是 cv 限定的)void 类型,创建指定类型的纯右值,其值为 通过值初始化 (8.5) 类型 T 的对象产生; void() 情况没有进行初始化

请注意,它明确指出void() 是合法的。

† 我的链接是 N4296,它是 C++14 之前的最后一个公共委员会草案,但是标准的各种版本在这里没有变化。


编辑

有用吗?明明这样?不,我看不出它有什么用。但是,它在模板函数中很有用,这些函数有时会执行以下操作:

template <typename T>
T foo() {
    if (prepare_for_for()) {
        return do_foo();
    } else {
        return T();
    }
}

这将有效,即使对于 T == void

【讨论】:

  • 这说明它是合法的(+1),但它也有用吗?
  • @FabioTurati:不幸的是,我的问题实际上是两个问题。这个问题下带有 0x5f3759df cmets 的答案回答了第二部分。
【解决方案2】:

从语法上讲,void() 是一种以功能表示法编写的显式类型转换(参见 5.2.3)。

请注意,即使在“经典”C (C89/90) 中,已允许显式转换为 void。当然,在 C 中必须使用“经典”C 风格的强制转换符号并提供参数。在 C 中,任何表达式都可以转换为 void,包括已经是 void 的表达式。此功能未更改地迁移到 C++ 中显式类型转换的cast notation(它由其功能的static_cast 分支处理,即您可以在C++ 中将static_cast 转换为void)。

考虑到上述情况,转换为void 也始终得到替代 C++ 强制转换语法的支持 - 函数式表示法 也就不足为奇了。一旦你理解了这一点,它被扩展为支持“无参数”版本也就不足为奇了 - void()

this 在 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 并且不接受任何参数。

【讨论】:

  • 一个不太容易接受的事实是 void 是一个不完整的类型(我刚学过),但它可以用作转换目标。如何将值转换为不完整的类型?这有点奇怪。但现在我理解了这种行为。
  • @geza:可以说void 在这方面是特殊的。在 C 和 C++ 中,这种转换都给出了单独的描述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
  • 2011-08-01
  • 1970-01-01
  • 2012-07-16
相关资源
最近更新 更多