我能在不返回void的函数上使用[[noreturn]]吗?

20

我以前从没见过在非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;

这会导致任何未定义的行为吗?


3
你可能会在实现允许假设无限循环结束的情况下遇到学究式的问题。 - chris
@chris 我希望也能用[[maybe_unused]]标记返回值。 - Trevor Hickey
4
您提供的链接中写道:“如果带有此属性的函数实际返回,其行为是未定义的。” - 101010
3个回答

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

noreturn 属性指定函数不会返回。它应该最多出现一次在每个 attribute-list 中,并且不应该有任何 attribute-argument-clause 存在。该属性可以应用于函数声明中的 declarator-id 上。如果某个函数的任何声明指定了 noreturn 属性,则该函数的第一个声明应指定 noreturn 属性。如果一个函数在一个翻译单元中被声明为带有 noreturn 属性,而在另一个翻译单元中被声明为不带有 noreturn 属性,则程序是非法的;无需进行诊断。

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

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

10

从C++标准的§7.6.8/p2 Noreturn attribute [dcl.attr.noreturn]中可以得知:

如果调用了一个之前被声明为带有noreturn属性的函数f,并且f最终返回了,那么其行为是未定义的。 [注意:该函数可能通过抛出异常来终止。—注] [注意:如果标记为[[noreturn]]的函数可能会返回,则鼓励实现发出警告。—注]

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


5
这怎么回答问题了呢?原帖作者知道它不应该返回任何内容,他正在询问它的类型。 - Patrick Collins
标准引用如何澄清它ub?OP的函数最终没有返回。 - Barry
@Barry它不是返回0吗? - 101010
@101010 它永远不会执行到那一行。 - Barry

1

我找到了一个非void [[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)。

还适用于回调函数,当返回类型预定时。 - Toby Speight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接