解析C++中的 noexcept


一. 概述

noexcept 是C++11中的特性,既是一個說明符,也是一個運算符。能夠說明函數是否會拋出異常,如下:

 1 struct X {
 2 
 3     int f() const noexcept {
 4         return 58;
 5     }
 6 
 7     void g() noexcept {}
 8 };
 9 
10 int foo() noexcept {
11     return 42;
12 }

noexcept指示上述的幾個函數不會拋出異常,編譯器可以優化代碼。

如果有異常拋出,則會調用std::terminate結束生命周期。

 

二. 帶參數的noexcept

帶參數的noexcept作用為:如果noexcept(true),則不會拋出異常,反之則可能有異常,下面的例子中,可以用noexcept檢查傳入模板參數是不是基礎類型。

1 template <class T>
2 T copy(const T& o) noexcept(std::is_fundamental<T>::value) {
3     ...
4 }

這個函數可以優化為:

1 template <class T>
2 T copy(const T& o) noexcept(noexcept (T(o))) {
3     
4 }

這里用了2個noexcept,第二個判斷T(o)是否可能拋出異常,第一個接受第二個的返回值,決定T類型復制函數是否聲明為不拋出異常

 

三. noexcept使用場景

1. 解決移動構造和移動賦值的問題

下例用noexcept實現一個移動語義的容器經常用到的工具函數swap。如果move沒有拋出異常的可能,那么函數進行移動操作,否則進行復制操作。

1 template <class T>
2 void swap(T &a, T &b)
3 noexcept(noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b)))) {
4     static_assert (noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b))) );
5     T temp(std::move(a));
6     a = std::move(b);
7     b = std::move(temp);
8 }

2. 用於析構函數。在新版本的編譯器中,析構函數是默認加上關鍵字noexcept的。

3. 葉子函數。葉子函數是指在函數內部不分配棧空間,也不調用其它函數,也不存儲非易失性寄存器,也不處理異常。

 

四. 注意事項

1. 在新版本編譯器中,默認構造函數,默認復制構造函數,默認賦值函數,默認移動構造函數,默認移動賦值函數均自帶noexcept,但使用者自定義或重載的上述函數需要手動加上noexcept才有此功能。

2. c++11中保留了throw(), 實現和noexcept類似的功能,區別是throw()不會針對編譯器進行優化,但是C++20中移除了throw()。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM