官术网_书友最值得收藏!

1.5 C++17注解標簽(attributes)

在C++98/03時代,不同的編譯器使用不同的注解為代碼增加了一些額外的說明,讀者可能在各種C/C++代碼中見過#pragma、__declspec、__attribute等注解。然而,不同的編譯器對于同一功能可能使用不同的注解,導致我們需要為不同的編譯器編寫不同的注解代碼。從C++11開始,新的語言標準統一制定了一些常用的注解標簽,本節介紹一些比較常用的注解標簽。使用注解標簽的語法如下:

這些標簽可用于修飾任意類型、函數或者enumeration,在C++17之前不能用于修飾命名空間(namespace)和enumerator,在C++17標準中,這個限制也被取消了。

1.5.1 C++98/03的enumeration和C++11的enumerator

讀者可能對enumeration和enumerator這兩個詞感到困惑,前者指的是從C時代就存在的不限定作用域的枚舉。例如,下面的枚舉類型就是一個enumeration:

這種枚舉類型之所以被稱為不限定作用域的枚舉,是因為一旦定義了這樣一種枚舉,在其所在的作用域內就不能再定義與之同名的變量了。例如,如果定義了上述Color枚舉,此時再定義一個名為 white 的變量,就無法編譯通過了。而 enumerator 指的是從 C++11開始引入的以如下形式定義的枚舉變量:

此時,由于枚舉值white對外部不可見(必須通過Color::white引用),所以可以定義一個同名的white變量。這種枚舉變量被稱為限定作用域的枚舉。

1.5.2 C++17的注解標簽

在分清楚enumeration和enumerator之后,讓我們回到正題上來。

C++11引入的常用注解標簽有[[noreturn]],這個注解的含義是告訴編譯器某個函數沒有返回值,例如:

這個標簽一般在設計一些系統函數時使用,例如std::abort()和std::exit()。

C++14 引入了[[deprecated]]標簽來表示一個函數或者類型等已被棄用,在使用這些被棄用的函數或者類型并編譯時,編譯器會給出相應的警告,有的編譯器直接生成編譯錯誤:

這個標簽在實際開發中非常有用,尤其在設計一些庫代碼時,如果庫作者希望某個函數或者類型不想再被用戶使用,則可以使用該標注標記。當然,我們也可以使用如下語法給出編譯時的具體警告或者出錯信息:

有如下代碼:

若在main函數中調用被標記為deprecated的函數funcX,則在gcc/g++7.3中編譯時會得到如下警告信息:

Java 開發者對這個標注應該再熟悉不過了。在 Java 中使用@Deprecated 標注可以達到同樣的效果,這大概是 C++標準委員“拖欠”廣大 C++開發者太久的一個特性吧。

C++17提供了三個實用注解:[[fallthrough]]、[[nodiscard]]和[[maybe_unused]],這里逐一介紹它們的用法。

[[fallthrough]]用于 switch-case 語句中,在某個 case 分支執行完畢后如果沒有 break語句,則編譯器可能會給出一條警告。但有時這可能是開發者有意為之的。為了讓編譯器明確知道開發者的意圖,可以在需要某個 case分支被“貫穿”的地方(上一個case沒有break語句)顯式設置[[fallthrough]]標記。代碼示例如下:

注意:在gcc/g++中,[[fallthrough]]后面的分號不是必需的,在Visual Studio中必須加上分號,否則無法編譯通過。

熟悉Golang的讀者,可能對fallthrough這一語法特性非常熟悉,Golang中在switch-case后加上fallthrough,是一個常用的告訴編譯器意圖的語法規則。代碼示例如下。

[[nodiscard]]一般用于修飾函數,告訴函數調用者必須關注該函數的返回值(即不能丟棄該函數的返回值)。如果函數調用者未將該函數的返回值賦值給一個變量,則編譯器會給出一個警告。例如,假設有一個網絡連接函數 connect,我們通過返回值明確說明了連接是否建立成功,則為了防止調用者在使用時直接將該值丟棄,我們可以將該函數使用[[nodiscard]]標記:

在C++20中,對于諸如operator new()、std::allocate()等庫函數均使用了[[nodiscard]]進行標記,以強調必須使用這些函數的返回值。

在通常情況下,編譯器會對程序代碼中未使用的函數或變量給出警告,另一些編譯器干脆不允許通過編譯。在C++17之前,程序員為了消除這些未使用的變量帶來的編譯警告或者錯誤,要么修改編譯器的警告選項設置,要么定義一個類似于UNREFERENCED_PARAMETER的宏來顯式調用這些未使用的變量一次,以消除編譯警告或錯誤:

以上代碼節選自一個標準 Win32 程序的結構,其中的函數參數 hPrevInstance 和lpCmdLine一般不會被用到,編譯器會給出警告。為了消除這類警告,這里定義了一個宏UNREFERENCED_PARAMETER并進行調用,造成這兩個參數被使用的假象。

有了[[maybe_unused]]注解之后,我們就再也不需要這類宏來“欺騙”編譯器了。以上代碼使用該注解后可以修改如下:

讀者可以通過C++官網了解C++新標準中更多注解的用法。

主站蜘蛛池模板: 佛山市| 宜兰县| 古浪县| 崇礼县| 新昌县| 巢湖市| 体育| 上饶市| 尼木县| 安泽县| 五原县| 黑山县| 陵川县| 灌云县| 南京市| 仁化县| 阳山县| 石狮市| 光泽县| 清丰县| 灵山县| 曲水县| 沭阳县| 连南| 全椒县| 工布江达县| 大方县| 如东县| 揭东县| 页游| 建水县| 荆州市| 边坝县| 察隅县| 呼玛县| 广安市| 普陀区| 崇礼县| 通山县| 定兴县| 崇阳县|