C++ 不归路的意义何在?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10538291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the point of noreturn?
提问by B?ови?
[dcl.attr.noreturn]provides the following example:
[dcl.attr.noreturn]提供了以下示例:
[[ noreturn ]] void f() {
throw "error";
// OK
}
but I do not understand what is the point of [[noreturn]]
, because the return type of the function is already void
.
但我不明白有什么意义[[noreturn]]
,因为函数的返回类型已经是void
.
So, what is the point of the noreturn
attribute? How is it supposed to be used?
那么,noreturn
属性的意义是什么?它应该如何使用?
回答by sepp2k
The noreturn attribute is supposed to be used for functions that don't return to the caller. That doesn't mean void functions (which do return to the caller - they just don't return a value), but functions where the control flow will not return to the calling function after the function finishes (e.g. functions that exit the application, loop forever or throw exceptions as in your example).
noreturn 属性应该用于不返回给调用者的函数。这并不意味着 void 函数(它们确实返回给调用者 - 它们只是不返回值),而是在函数完成后控制流不会返回到调用函数的函数(例如退出应用程序的函数,永远循环或在您的示例中抛出异常)。
This can be used by compilers to make some optimizations and generate better warnings. For example if f
has the noreturn attribute, the compiler could warn you about g()
being dead code when you write f(); g();
. Similarly the compiler will know not to warn you about missing return statements after calls to f()
.
编译器可以使用它来进行一些优化并生成更好的警告。例如,如果f
具有 noreturn 属性,编译器会g()
在您编写f(); g();
. 类似地,编译器将知道在调用f()
.
回答by Stephen Canon
noreturn
doesn't tell the compiler that the function doesn't return any value. It tells the compiler that control flow will not return to the caller. This allows the compiler to make a variety of optimizations -- it need not save and restore any volatile state around the call, it can dead-code eliminate any code that would otherwise follow the call, etc.
noreturn
不会告诉编译器该函数不返回任何值。它告诉编译器控制流不会返回给调用者。这允许编译器进行各种优化——它不需要保存和恢复调用周围的任何易失性状态,它可以死代码消除任何可能跟随调用的代码,等等。
回答by David Rodríguez - dribeas
It means that the function will not complete. The control flow will never hit the statement after the call to f()
:
这意味着该功能将无法完成。在调用 之后,控制流永远不会命中该语句f()
:
void g() {
f();
// unreachable:
std::cout << "No! That's impossible" << std::endl;
}
The information can be used by the compiler/optimizer in different ways. The compiler can add a warning that the code above is unreachable, and it can modify the actual code of g()
in different ways for example to support continuations.
编译器/优化器可以以不同方式使用这些信息。编译器可以添加上面代码不可访问的警告,并且它可以g()
以不同的方式修改实际代码,例如支持延续。
回答by Nadav Har'El
Previous answers correctly explained what noreturn is, but not whyit exists. I don't think the "optimization" comments is the main purpose: Functions which do not return are rare and usually do not need to be optimized. Rather I think the main raison d'être of noreturn is to avoid false-positive warnings. For example, consider this code:
以前的答案正确地解释了 noreturn 是什么,但没有解释它为什么存在。我不认为“优化”注释是主要目的:不返回的函数很少见,通常不需要优化。相反,我认为 noreturn 的主要存在理由是避免误报警告。例如,考虑以下代码:
int f(bool b){
if (b) {
return 7;
} else {
abort();
}
}
Had abort() not been marked "noreturn", the compiler might have warned about this code having a path where f does not return an integer as expected. But because abort() is marked no return it knows the code is correct.
如果 abort() 没有被标记为“noreturn”,编译器可能会警告这段代码有一个路径,其中 f 没有按预期返回整数。但是因为 abort() 被标记为不返回,所以它知道代码是正确的。
回答by Elazar
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 allthe 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
是其他语言中所称的unit
或top
. 它的逻辑等价物是True。任何值都可以合法地强制转换为void
(每个类型都是 的子类型void
)。把它想象成“宇宙”集合;世界上的所有值没有共同的操作,因此对 type 的值没有有效的操作void
。换句话说,告诉你某物属于宇宙集不会给你任何信息——你已经知道了。所以以下是合理的:
(void)5;
(void)foo(17); // whatever foo(17) does
But the assignment below is not:
但下面的任务不是:
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 highlyinformative - 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
.
[[noreturn]]
,另一方面,有时也被称为empty
,Nothing
,Bottom
或Bot
和是的逻辑等效假。它根本没有值,并且这种类型的表达式可以转换为(即子类型)任何类型。这是空集。请注意,如果有人告诉您“表达式 foo() 的值属于空集”,它会提供大量信息 - 它告诉您该表达式永远不会完成其正常执行;它将中止、抛出或挂起。它与 完全相反void
。
So the following does not make sense (pseudo-C++, since noreturn
is not a first-class C++ type)
所以以下没有意义(伪C++,因为noreturn
不是一流的C++类型)
void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns
But the assignment below is perfectly legitimate, since throw
is understood by the compiler to not return:
但是下面的赋值是完全合法的,因为throw
编译器理解它不会返回:
void f(int y) {
int x = y!=0 ? 100/y : throw exception();
cout << x << endl;
}
In a perfect world, you could use noreturn
as the return value for the function raise()
above:
在完美的世界中,您可以使用noreturn
作为上述函数的返回值raise()
:
noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();
Sadly C++ does not allow it, probably for practical reasons. Instead it gives you the ability to use [[ noreturn ]]
attribute which helps guiding compiler optimizations and warnings.
遗憾的是,C++ 不允许这样做,可能是出于实际原因。相反,它使您能够使用[[ noreturn ]]
有助于指导编译器优化和警告的属性。