1. 程式人生 > 其它 >noexcept修飾符,noexcept操作符

noexcept修飾符,noexcept操作符

目錄

noexcept的兩個作用:
1)作為noexcept修飾符,宣告函式是否丟擲異常;
2)作為noexcept操作符,判斷表示式是否丟擲異常;

noexcept修飾符

noexcept修飾符有兩種形式:一種是簡單在函式聲明後加noexcept,另一種是接受一個常量表達式作為引數,如:

void except_func() noexcept;            // 這裡noexcept作為修飾符
void except_func() noexcept(常量表達式); // 這裡noexcept作為運算子

宣告為noexcept的函式丟擲了異常,會怎麼樣?
如果一個函式宣告為noexcept,但還是丟擲了異常,會直接呼叫std::terminate中斷程式的執行。

注:C++98中,用throw()來宣告不丟擲異常,throw(異常型別)宣告可能丟擲的異常型別。noexcept效率比throw更高一些,因為編譯器可以用std::terminate()來終止程式執行,而throw異常機制會有一些額外開銷,如函式棧依次展開並析構自動變數。

例1,C++98中,用throw()宣告不丟擲異常的函式:

template<class T> class A{
public:
    static constexpr T min() throw() { return T(); }
    static constexpr T max() throw() { return T(); }
    static constexpr T lowest() throw() { return T(); }
...
};

相應地,在C++11中,使用noexcept替換throw()

template<class T> class A{
public:
    static constexpr T min() noexcept { return T(); }
    static constexpr T max() noexcept { return T(); }
    static constexpr T lowest() noexcept { return T(); }
...
};

noexcept操作符

noexcept普通形式

noexcept(e);

可以讓一個函式f()是否丟擲異常,與另一個函式g()保持一致:

void f() noexcept(noexcept(g())); // f和g的異常說明保持一致

改寫成讓f()是否丟擲異常,取決於模板引數T()表示式:

template<class T>
void f() noexcept(noexcept(T())) { }

例2,C++98中,用throw()宣告可能丟擲std::bad_alloc異常的函式:

void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);

相應地,C++11中,可用noexcept(false)來替代throw

void* operator new(std::size_t) noexcept(false);
void* operator new[](std::size_t) noexcept(false);

可以看到,noexcept宣告函式可能丟擲的異常時,無需指明具體的型別,而throw卻需要指明。

不過,出於安全考慮,C++11標準中,類的解構函式預設是noexcept(true)。如果顯示指定noexcept或noexcept(false),就不會再保持預設值。

參考

[1]MichaelWon, IBM XL編譯器中國開發團隊. 深入理解C++11:C++11新特性解析與應用[M]. 機械工業出版社, 2013.