以下代码在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
说明符成为本标准修订版中函数类型的一部分。
答案 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)
main
中int main() noexcept;
的类型是“C ++ 14中()
返回int
”的函数和{{1}的noexcept
函数在C ++ 17中返回()
“。
前者明确要求[basic.start.main]支持。后者不是。
这看起来像C ++ 17中的缺陷。