19

我以前从未见过在非 void 返回函数上使用 [[ noreturn ]] 。

以下定义是否明确?

[[ noreturn ]] int function();

int function(){
  while(true){/* impl */}
  return 0;
}

返回类型必须是 的原因int是因为该函数通过函数指针传递给另一个函数。

所以假设调用者看起来像这样:

//call the non-returning function
int var = (*fptr)();

//use var some way (even though the function will never actually return)
std::cout << var;

这会表现出任何未定义的行为吗?

4

3 回答 3

24

标准规范[[noreturn]]在 [dcl.attr.noreturn] 中。整个规范性文本如下:

属性标记 noreturn指定函数不返回。它在每个属性列表中最多出现一次,并且不应出现任何属性参数子句。该属性可以应用于函数声明中的declarator-idnoreturn 如果该函数的任何声明指定了该属性,则该函数的第一个声明应指定该noreturn属性。如果一个函数noreturn在一个翻译单元中声明了该属性,而同一函数noreturn 在另一个翻译单元中声明为没有该属性,则程序是非良构的;无需诊断。

如果在先前使用属性声明的f位置调用函数并最终返​​回,则行为未定义。fnoreturnf

没有提到返回类型。唯一重要的是函数不返回。如果函数返回(无论是voidorint还是vector<vector<double>>),则行为未定义。如果函数不返回,则返回类型无关紧要。

于 2016-07-27T21:15:19.140 回答
10

来自 C++ 标准§7.6.8/p2 Noreturn 属性 [dcl.attr.noreturn](Emphasis Mine

如果在 f 之前使用 noreturn 属性声明的地方调用函数 f 并且 f 最终返回,则行为未定义。[注意:该函数可能会通过抛出异常终止。— end note ] [ 注意:如果标记为 [[noreturn]] 的函数可能返回,则鼓励实现发出警告。——尾注]

由于您的功能永远不会到达,return 0;因此没有 UB。

于 2016-07-27T21:15:47.870 回答
0

我发现了一个非空[[noreturn]]函数的实际例子。在某种情况下,当在?:运算符中使用以提供正确的结果类型的?:运算符时:

template <class T> [[noreturn]] T fail(char const *s) noexcept { puts(s); exit(1); }
enum E { V1, V2 };
int f(E e) {
  return (e == V1) ? 1 : (e == V2) ? 2 : fail<E>("bad e");
}

注意:人们可能会有一种感觉,在计算结果类型时可以忽略运算符中的[[noreturn]]函数。但这是不可能的,因为它不是表达式结果类型的一部分(有结果类型而不是)。?:?:[[noreturn]]fail<T>("")T[[noreturn]] T

于 2021-08-06T15:02:02.547 回答