不归路的意义何在



[dcl.attr.noreturn] 提供了以下示例:

[[ noreturn ]] void f() {
    throw "error";
    // OK
}

但是我不明白[[noreturn]]有什么意义,因为函数的返回类型已经void了。

那么,noreturn属性的意义何在?应该如何使用?

[[noreturn]] 属性应该用于不返回给调用方的函数。这并不意味着void函数(它们确实返回给调用方 - 它们只是不返回值(,而是控制流在函数完成后不会返回到调用函数的函数(例如,退出应用程序的函数,永远循环或抛出异常,如您的示例所示(。

编译器可以使用它来进行一些优化并生成更好的警告。例如,如果f具有 [[noreturn]] 属性,则编译器可以在您编写f(); g();时警告您g()是死代码。同样,编译器将知道在调用 f() 后不要警告您缺少return语句。

noreturn不会

告诉编译器该函数不返回任何值。 它告诉编译器控制流不会返回到调用方。 这允许编译器进行各种优化 - 它不需要保存和恢复调用周围的任何易失状态,它可以死代码消除任何代码,否则会跟随调用,等等。

这意味着函数将无法完成。控制流在调用 f() 后永远不会命中语句:

void g() {
   f();
   // unreachable:
   std::cout << "No! That's impossible" << std::endl;
}

编译器/优化器可以以不同的方式使用该信息。编译器可以添加警告,指出上述代码无法访问,并且可以以不同的方式修改g()的实际代码,例如支持延续。

前面的回答正确地解释了noreturn是什么,但没有解释它为什么存在。我不认为"优化"注释是主要目的:不返回的函数很少见,通常不需要优化。相反,我认为不归路的主要存在理由是避免误报警告。例如,请考虑以下代码:

int f(bool b){
    if (b) {
        return 7;
    } else {
        abort();
    }
 }

如果 abort(( 没有被标记为"noreturn",编译器可能会警告此代码的路径,其中 f 不会按预期返回整数。但是因为 abort(( 被标记为没有返回,所以它知道代码是正确的。

类型 从理论上讲,void是其他语言中unittop所说的。它的逻辑等价物是 True。任何值都可以合法地转换为void(每个类型都是 void 的子类型(。把它想象成"宇宙"集;世界上所有值没有通用的操作,因此对类型 void 的值没有有效的操作。換句話說,告訴你某個東西屬於宇宙集,不會給你任何信息——你已經知道了。所以以下几点是合理的:

(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]]有时被称为emptyNothingBottomBot,在逻辑上等价于False。它根本没有值,这种类型的表达式可以强制转换为(即是(任何类型的表达式。这是空集。请注意,如果有人告诉你"表达式 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 ]]属性,这有助于指导编译器优化和警告。

最新更新