我可以在非void返回函数上使用[[noreturn]]吗?

时间:2016-07-27 21:03:26

标签: c++ c++11 return undefined-behavior noreturn

我之前从未见过使用非空返回函数的[[ 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;

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

3 个答案:

答案 0 :(得分:24)

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

  

attribute-token noreturn指定函数不返回。它最多只能出现一次   每个属性列表并且不存在 attribute-argument-clause 。该属性可以应用于   函数声明中的 declarator-id 。函数的第一个声明应指定noreturn   如果该函数的任何声明指定noreturn属性,则为attribute。如果声明了一个函数   一个翻译单元中的noreturn属性和相同的函数在没有noreturn的情况下声明   属于另一个翻译单元,该程序是不正确的;无需诊断。

     

如果调用函数f,之前使用f属性声明了noreturn,并且f最终返回,   行为未定义。

没有提及返回类型。唯一重要的是功能不归。如果函数返回(voidintvector<vector<double>>),则行为未定义。如果函数没有返回,则返回类型并不重要。

答案 1 :(得分:10)

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

  

如果调用函数f,其中f先前已使用   noreturn属性和f最终返回,行为是   undefined。 [注意:该函数可以通过抛出一个函数来终止   例外。 - 尾注] [注:鼓励实施   如果标记为[[noreturn]]的函数可能返回,则发出警告。 - 结束   注意]

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

答案 2 :(得分:0)

我发现了一个非空函数 docker volume rm 的实际例子。在一种情况下,当在 [[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)。