[dcl.attr。Noreturn]的示例如下:
[[ noreturn ]] void f() {
throw "error";
// OK
}
但我不明白[[noreturn]]的意义是什么,因为函数的返回类型已经是void。
noreturn属性的意义是什么?它应该如何使用?
[dcl.attr。Noreturn]的示例如下:
[[ noreturn ]] void f() {
throw "error";
// OK
}
但我不明白[[noreturn]]的意义是什么,因为函数的返回类型已经是void。
noreturn属性的意义是什么?它应该如何使用?
这意味着函数不会完成。在调用f()之后,控制流永远不会碰到语句:
void g() {
f();
// unreachable:
std::cout << "No! That's impossible" << std::endl;
}
编译器/优化器可以以不同的方式使用这些信息。编译器可以添加一个警告,说明上面的代码不可达,并且它可以以不同的方式修改g()的实际代码,例如支持延续。
Noreturn不会告诉编译器函数不返回任何值。它告诉编译器控制流不会返回给调用者。这允许编译器进行各种优化——它不需要保存和恢复调用周围的任何易变状态,它可以消除任何死代码,否则会跟随调用,等等。
[[noreturn]]属性应该用于不返回调用者的函数。这并不意味着void函数(它们确实返回给调用方——只是不返回值),而是在函数结束后控制流不会返回给调用方的函数(例如,退出应用程序的函数,永远循环或抛出异常,如你的例子)。
编译器可以使用它来进行一些优化并生成更好的警告。例如,如果f具有[[noreturn]]属性,当你编写f()时,编译器会警告你g()是死代码;g();。类似地,编译器将知道在调用f()后不要警告你错过return语句。
Type theoretically speaking, void is what is called in other languages unit or top. Its logical equivalent is True. Any value can be legitimately cast to void (every type is a subtype of void). Think about it as "universe" set; there are no operations in common to all the values in the world, so there are no valid operations on a value of type void. Put it another way, telling you that something belongs to the universe set gives you no information whatsoever - you know it already. So the following is sound:
(void)5;
(void)foo(17); // whatever foo(17) does
但下面的作业不是:
void raise();
void f(int y) {
int x = y!=0 ? 100/y : raise(); // raise() returns void, so what should x be?
cout << x << endl;
}
[[noreturn]], on the other hand, is called sometimes empty, Nothing, Bottom or Bot and is the logical equivalent of False. It has no values at all, and an expression of this type can be cast to (i.e is subtype of) any type. This is the empty set. Note that if someone tells you "the value of the expression foo() belongs to the empty set" it is highly informative - it tells you that this expression will never complete its normal execution; it will abort, throw or hang. It is the exact opposite of void.
所以下面的代码没有意义(伪c++,因为noreturn不是一流的c++类型)
void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns
但是下面的赋值是完全合法的,因为编译器认为throw不返回:
void f(int y) {
int x = y!=0 ? 100/y : throw exception();
cout << x << endl;
}
在完美的情况下,你可以使用noreturn作为上面raise()函数的返回值:
noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();
遗憾的是,c++可能出于实际原因不允许这样做。相反,它让你能够使用[[noreturn]]属性,帮助指导编译器优化和警告。
前面的答案正确地解释了noreturn是什么,但没有解释它为什么存在。我不认为“优化”注释是主要目的:不返回的函数很少,通常不需要优化。相反,我认为无回报的主要原因是为了避免假阳性警告。例如,考虑以下代码:
int f(bool b){
if (b) {
return 7;
} else {
abort();
}
}
如果abort()没有被标记为“noreturn”,编译器可能会警告这段代码的路径中f没有像预期的那样返回整数。但是因为abort()被标记为no return,所以它知道代码是正确的。