可以使用“noexcept”说明符声明“main”函数吗?

时间:2017-11-30 22:44:42

标签: c++ language-lawyer main c++17 noexcept

以下代码在C ++中是否有效?

int main() noexcept
{
}

clang ++ 3.8.0 g ++ 7.2.0 compile it fine(带-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors编译标志)。

是否允许在noexcept函数的noexcept规范中使用复杂条件(例如包括main运算符)?

那么C ++ 17呢?据我所知,noexcept说明符成为本标准修订版中函数类型的一部分。

2 个答案:

答案 0 :(得分:20)

标准[ [basic.start.main] ]指定main函数的以下约束:

  

实施应允许两者:

     

- ()返回int和

的函数      

- 返回int

的函数(int,指向char的指针)

此外:

  

将main定义为已删除或声明main为inline,static或constexpr的程序格式不正确。

实际上,noexcept没有关于main限定符的说明。另一方面,noexcept被允许作为任何函数的说明符。这意味着main noexcept

noexcept主要有什么不同?

由于我们已经看到noexcept函数的main标准不是很明确,我们可以尝试扣除一些行为并检查实现。

来自here

  

每当抛出异常并且搜索处理程序遇到非抛出函数的最外层时,就会调用函数std :: terminate。

虽然例外的一般规则来自here

  

如果抛出异常并且未捕获异常,包括转义std :: thread的初始函数,main函数以及任何静态或线程局部对象的构造函数或析构函数的异常,则调用std :: terminate 。它是实现定义的,是否会对未捕获的异常进行任何堆栈展开。

这意味着来自throw函数main始终会生成std::terminate次调用。无论noexcept的{​​{1}}规范如何。

实施方:

确实,以下代码:

main

int main(int argc, char* argvp[]) {
  throw 1;
  return 0;
}

将生成相同的输出程序集。例如,在GCC中:

int main(int argc, char* argvp[]) noexcept {
  throw 1;
  return 0;
}

这意味着它将被解析为main: movl $4, %edi subq $8, %rsp call __cxa_allocate_exception xorl %edx, %edx movl $1, (%rax) movl typeinfo for int, %esi movq %rax, %rdi call __cxa_throw 的调用,因为无论std::terminate规范如何,堆栈帧在“主级别”都是空的。

答案 1 :(得分:8)

mainint main() noexcept;的类型是“C ++ 14中()返回int”的函数和{{1}的noexcept函数在C ++ 17中返回()“。

前者明确要求[basic.start.main]支持。后者不是。

这看起来像C ++ 17中的缺陷。