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

Con*_*tor 26 c++ program-entry-point language-lawyer noexcept c++17

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

int main() noexcept
{
}
Run Code Online (Sandbox Code Playgroud)

铛++ 3.8.0克++ 7.2.0 编译它细(与-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors编译标志).

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

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

Bia*_*sta 20

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

实施应允许两者:

- 返回int和的函数()

- 返回int的函数(int,指向char的指针)

此外:

将main定义为已删除或将main声明为内联,静态或constexpr的程序是不正确的.

在实践中,没有关于noexcept限定符的规范main.另一方面,noexcept允许作为任何函数的说明符.这将意味着main noexcept没有 形成不良.


主要有什么区别noexcept

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

这里:

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

虽然是例外的一般规则,从这里:

如果抛出一个异常,并没有被捕获,包括逃脱的std ::线程的初始功能,主要功能,以及任何静态或本地线程对象的构造函数和析构函数的异常,那么标准::终止被调用.它是实现定义的,是否对未捕获的异常进行任何堆栈展开.

这意味着throwfrom main函数总是生成一个std::terminate调用.无论noexcept规格如何main.

实施方:

确实,以下代码:

int main(int argc, char* argvp[]) {
  throw 1;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

int main(int argc, char* argvp[]) noexcept {
  throw 1;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

将生成相同的输出组件.例如在GCC中:

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
Run Code Online (Sandbox Code Playgroud)

这意味着它将被解析为一个调用,std::terminate因为无论noexcept规范如何,堆栈帧在"主级别"都是空的.


T.C*_*.C. 8

的类型的mainint main() noexcept;是"的函数()返回int在C++ 14和"" noexcept的函数()返回int在C++ 17".

前者显然需要[basic.start.main]支持.后者不是.

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

  • 报告核心问题比我更热心的人应该联系EDG的CWG主席Mike Miller,以便 - 假设之前没有报告过 - 这个问题将在两年后出现在核心问题清单上. (3认同)