【问题标题】:Why is g++ allowing me to treat this void-function as anything but?为什么 g++ 允许我将这个 void-function 视为除此之外的任何东西?
【发布时间】:2014-01-22 07:29:48
【问题描述】:

为什么以下代码在 GCC 4.8 (g++) 中编译?它不是完全不合格式吗?

void test(int x)
{
    return test(3);
}

int main() {}
  1. 我正在尝试使用调用test的结果,它不存在
  2. 我正在尝试从test 返回一个值

两者都应该是根本不可能的 - 不仅仅是 UB,据我记得 - 使用 void 返回类型。

我得到的唯一警告是关于 x 未被使用,甚至没有关于添加非标准隐式返回类型的任何内容。

Live demo

【问题讨论】:

  • 这与 void 类型的对象无关。 void 类型的表达式丢弃值表达式
  • 一旦你调用这个函数,它应该会产生一个Segmentation fault
  • @dan:或者堆栈溢出,或者具有无限调用深度的非终止程序的其他一些实际后果。这可能包括我的程序自发地发展感知力并在工作中给你打电话。 :)
  • 注意:这并不特定于 C++11。自 C++98/03 以来,我们已经能够编写 return f(); 而不是 { f(); return; }(给定 void f();)。 TC++PL3 §7.3(第 148 页)说“在编写返回类型是模板参数的模板函数时,这种形式的返回很重要”。
  • void 自 C++98 以来一直是不完整的类型。您能否提供有关 void 在 C++11 中不再不完整的信息?

标签: c++ gcc c++11


【解决方案1】:

这是标准允许的 (§6.6.3/3)

带有 void 类型表达式的 return 语句只能在返回类型为 cv void 的函数中使用;表达式在函数返回给它的调用者之前被计算。

【讨论】:

  • 是的,这是正确的。整个事情变成了无操作。值得注意的是,这在 C++03 中也是如此,而且非常愚蠢。
  • @LightnessRacesinOrbit:我猜它在返回类型可能是也可能不是 void 的模板中很有用。
  • @Mat:我想我仍然希望那里的不良形式,让 SFINAE 开辟其他选择。如果没有别的,它只会让这个真的对于非模板代码来说是可怕的。 :(
  • @LightnessRacesinOrbit:我猜你不能切换到 C,这是禁止的? (-:
  • 它可能有它的用途。给定一个函数void error_reporter(...),您可以在一个返回void 的函数中编写代码:if (something > sommat_else) return error_reporter("the impossible occurred");,而不是在其中需要大括号和多个语句。这可能非常有用。
【解决方案2】:

至于为什么 GCC 允许它——当然是因为标准要求它是有效的。建立标准中规则基本原理的传递闭包,我很确定 GCC 允许这样做,因为它在模板事件中很有用

template<typename F>
typename std::result_of<F()>::type call(F f) {
  return f();
}

int main() {
   std::cout << call([]{ return 42; }) << std::endl;
   call([]{ std::cout << "I'm just an outputtor!" << std::endl; });
}

如您所见,call 不需要在 return 语句中为 void 做一个特殊情况。有点类似于x.~T() 的允许方式,即使T 最终为int

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2017-07-12
    相关资源
    最近更新 更多