noexcept

Version >= C++ 11

  1. 一元運算子,用於確定對其運算元的求值是否可以傳播異常。請注意,不檢查被呼叫函式的主體,因此 noexcept 可以產生錯誤否定。不評估運算元。

    #include <iostream>
    #include <stdexcept>
    void foo() { throw std::runtime_error("oops"); }
    void bar() {}
    struct S {};
    int main() {
        std::cout << noexcept(foo()) << '\n'; // prints 0
        std::cout << noexcept(bar()) << '\n'; // prints 0
        std::cout << noexcept(1 + 1) << '\n'; // prints 1
        std::cout << noexcept(S()) << '\n';   // prints 1
    }
    

    在這個例子中,即使 bar() 永遠不會丟擲異常,noexcept(bar()) 仍然是假的,因為 bar() 無法傳播異常這一事實尚未明確指定。

  2. 宣告函式時,指定函式是否可以傳播異常。單獨地,它宣告該函式不能傳播異常。使用帶括號的引數,它宣告函式可以或不可以根據引數的真值傳播異常。

    void f1() { throw std::runtime_error("oops"); }
    void f2() noexcept(false) { throw std::runtime_error("oops"); }
    void f3() {}
    void f4() noexcept {}
    void f5() noexcept(true) {}
    void f6() noexcept {
        try {
            f1();
        } catch (const std::runtime_error&) {}
    }
    

    在這個例子中,我們宣告 f4f5f6 不能傳播異常。 (雖然在執行 f6 期間可以丟擲異常,但它被捕獲並且不允許傳播出函式。)我們已經宣告 f2 可能傳播異常。當 noexcept 說明符被省略時,它相當於 noexcept(false),所以我們隱含地宣告 f1f3 可以傳播異常,即使在執行 f3 期間實際上不能丟擲異常。

Version >= C++ 17

函式是否為 noexcept 是函式型別的一部分:即,在上面的示例中,f1f2f3 具有與 f4f5f6 不同的型別。因此,noexcept 在函式指標,模板引數等方面也很重要。

void g1() {}
void g2() noexcept {}
void (*p1)() noexcept = &g1; // ill-formed, since g1 is not noexcept
void (*p2)() noexcept = &g2; // ok; types match
void (*p3)() = &g1;          // ok; types match
void (*p4)() = &g2;          // ok; implicit conversion