[dcl.attr.noreturn]提供以下示例:
[[ noreturn ]] void f() {
throw "error";
// OK
}
但我不明白这是什么意思[[noreturn]]
,因为该函数的返回类型已经存在void
。
那么,该noreturn
属性的意义是什么?应该如何使用?
[dcl.attr.noreturn]提供以下示例:
[[ noreturn ]] void f() {
throw "error";
// OK
}
但我不明白这是什么意思[[noreturn]]
,因为该函数的返回类型已经存在void
。
那么,该noreturn
属性的意义是什么?应该如何使用?
Answers:
noreturn属性应该用于不返回到调用方的函数。这并不意味着void函数(确实会返回调用者-它们只是不返回值),而是函数完成后控制流不会返回到调用函数的函数(例如,退出应用程序的函数,永久循环或抛出异常,如您的示例所示)。
编译器可以使用它进行一些优化并生成更好的警告。例如,如果f
具有noreturn属性,则编译器可能会g()
在您编写时警告您代码已死f(); g();
。同样,编译器会知道在调用后不会警告您关于缺少return语句的警告f()
。
execve
该不该回去,但是可能?它应该具有noreturn属性吗?
noreturn
属性。noreturn
仅在保证您的函数在控制流返回到调用方之前可以执行某些终止程序的情况下,例如,因为您调用exit(),abort(),assert(0)等
noreturn
。处理该异常与返回异常不同。try
调用后的任何代码仍然无法访问,否则void
将不会发生任何赋值或使用返回值的情况。
这意味着该功能将无法完成。调用以下命令后,控制流将永远不会命中该语句f()
:
void g() {
f();
// unreachable:
std::cout << "No! That's impossible" << std::endl;
}
该信息可以由编译器/优化器以不同方式使用。编译器可以添加一条警告,指出上面的代码不可访问,并且它可以g()
以不同的方式修改实际代码,例如以支持延续。
-Wno-return
您会收到警告。可能不是您所期望的那样,但是告诉您编译器已经了解了什么[[noreturn]]
并且可以利用它就足够了。(我有点惊讶的是-Wunreachable-code
没踢...)
-Wmissing-noreturn
,该警告表示流分析确定std::cout
无法访问。我不手边有一个新的gcc足以看生成的程序集,但如果调用我不会感到惊讶operator<<
滴
[[noreturn]]
从代码中推断出。如果此转换单元仅具有在其他地方定义的函数的声明,则编译器将无法删除该代码,因为它不知道该函数不会返回。这是该属性应有助于编译器的地方。
先前的答案正确地解释了什么是归还,但没有解释为什么它存在。我不认为“优化”注释的主要目的是:不返回的函数很少,通常不需要进行优化。相反,我认为不归还的主要理由是避免出现假阳性警告。例如,考虑以下代码:
int f(bool b){
if (b) {
return 7;
} else {
abort();
}
}
如果不将abort()标记为“ noreturn”,则编译器可能已警告该代码具有f不会按预期返回整数的路径。但是因为abort()被标记为没有返回,所以它知道代码是正确的。
从理论上讲,类型void
是其他语言unit
或所称的top
。其逻辑等效为True。任何值都可以合法地强制转换为void
(每种类型都是的子类型void
)。将其视为“宇宙”集合;世界上所有值都没有通用的运算,因此对type值没有有效的运算void
。换句话说,告诉您某物属于Universe集不会给您任何信息-您已经知道了。所以以下是声音:
(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]]
,另一方面,有时也被称为empty
,Nothing
,Bottom
或Bot
和是的逻辑等效假。它根本没有值,并且该类型的表达式可以强制转换为任何类型(即为该类型的子类型)。这是空集。请注意,如果有人告诉您“表达式foo()的值属于空集”,则它的信息量很高 -它告诉您该表达式将永远无法完成其正常执行;它会中止,抛出或挂起。与完全相反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 ]]
属性,该属性有助于指导编译器优化和警告。
void
,void
也永远不能对其进行评估。true
false
(void)true;
正如答案所示,它是完全有效的。void(true)
从语法上讲是完全不同的东西。试图void
通过调用带有true
参数的构造函数来创建新类型的对象。除其他原因外,这失败了,因为void
它不是一流的。