noreturn的意义是什么?
[dcl.attr.noreturn]提供了以下示例:
[[ noreturn ]] void f() { throw "error"; // OK }
但是我不明白[[noreturn]]
是什么意思,因为函数的返回types已经是void
。
那么, noreturn
属性的重点是什么? 它应该如何使用?
noreturn属性应该用于不返回给调用者的函数。 这并不意味着void函数(返回给调用者 – 它们只是不返回值),而是函数完成后控制stream不会返callback用函数的函数(例如,退出应用程序的函数,永远循环或抛出exception,如你的例子)。
这可以被编译器用来做一些优化并产生更好的警告。 例如,如果f
具有noreturn属性,那么在编写f(); g();
时,编译器会提醒你g()
是死代码f(); g();
f(); g();
。 同样,编译器将不会在调用f()
之后警告你缺less返回语句。
noreturn
不会告诉编译器该函数不会返回任何值。 它告诉编译器控制stream不会返回给调用者 。 这允许编译器进行各种优化 – 它不需要保存和恢复任何在调用周围的易失状态,它可以死代码消除任何本来会跟随调用的代码,等等。
这意味着该function将无法完成。 在调用f()
之后,控制stream将永远不会触发语句:
void g() { f(); // unreachable: std::cout << "No! That's impossible" << std::endl; }
这些信息可以被编译器/优化器以不同的方式使用。 编译器可以添加一个警告,说明上面的代码是不可访问的,它可以用不同的方式修改g()
的实际代码,例如支持延续。
从理论上讲, void
是其他语言unit
或top
所谓的。 其逻辑等价物是True 。 任何值都可以合法地转换为void
(每个types都是void
的子types)。 把它看作“宇宙”的集合; 世界上所有的值都没有共同的操作,所以对void
types的值没有有效的操作。 换一种说法,告诉你属于宇宙集的东西不会给你任何信息 – 你已经知道了。 所以下面是声音:
(void)5; (void)foo(); // whatever foo() 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
并且是False的逻辑等价物。 它根本没有任何值,而且这种types的expression式可以被转换成任何types的(即子types)。 这是空的集合。 请注意,如果有人告诉你“expression式foo()的值属于空集”这是非常有用的信息 – 它告诉你,这个expression式永远不会完成它的正常执行; 它会中止,抛出或挂起。 这是void
的完全相反。
所以下面没有意义(伪C ++,因为noreturn
不是一stream的C ++types)
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 ]]
属性来帮助指导编译器优化和警告。