C++11 的 10 個實用特性(上)

黃小非發表於2015-12-07

Kernel Panic 在這篇文章中總結了  C++11 中的 5 個實用特性:自動型別推導、強型別列舉、Unique 指標、static_assert、Lambdas 表示式。

自動型別推導

auto 關鍵字讓使用者得以使用 C++ 內建的型別推導特性。

Auto 關鍵字會對上述自變數(something)進行自動推導,得出其應該是 string 型別的結論,並在 auto 出現的地方用正確的型別進行替換。這個特性對迭代器特別有用。

上述程式碼可以寫成:

贊! 程式碼看上去簡潔多了!

強型別列舉

這個特性可以有效避免列舉型別的命名衝突,從而消除很多潛在的 bug。在舊版本的 C++ 中,程式設計師必須為每一個列舉項設定一個全域性唯一的名字。例如,如果你給一個列舉項取名叫 None,那麼其他的列舉集合就不能再用這個名字了。但是現在,你可以這麼做了!(譯註:作者下面給的例子彷彿和上面的文字不是非常搭配//myEnum ::All 和 myEnum::All是不是存在差異?)

Lambdas 表示式

Lambda 表示式簡單說就是個匿名函式(譯註:原文為in-place function,意思是“用來鑲嵌的函式”,但是匿名函式能更精確表達這個含義)。對於迭代器以及for 迴圈非常有用,這種函式你只需要在程式的某一處使用一次,所以沒有必要專門在程式裡明確定義它。Lambda 表示式並沒有讓 C++ 在邏輯表達上做到“及以往之不可及”的程度,它是一種受函數語言程式設計思想影響而引入的語言特性,能夠讓程式更緊湊。Lambda 表示式的最簡形式是下面這樣的:

[]() { }

加上所有可能的操作符,會是這樣:

其中[]是捕獲列表,()是引數列表,{}是函式體

Capture List 捕獲列表

捕獲列表定義了什麼型別的東西可以從 Lambda 表示式之外匹配到函式體中來。可以包含以下這些

  1. 一個值:[x]
  2. 一個引用 [&x]
  3. 當前範圍內任意變數的引用 [&]
  4. 同3,但是通過變數的值

你可以對上面的各項進行任意混合,只要用逗號隔開即可 [x, &y]

Argument List 引數列表

引數列表和 C++ 函式的引數列表是一個概念。

Function Body 函式體

函式體是指在 Lambda 表示式被呼叫時真正執行的程式碼。

Return Type Deduction

返回值推斷

如果 Lambda 表示式只有一個返回宣告,那麼返回值型別就可以省略,其型別就是隱式型別:decltype(return_statement)

可變 Labmda

如果一個 Lambda 表示式被標記為 mutable(例如:[]() mutable{ }),那麼對於按值捕獲的數值來說,在函式體內就允許對這些值進行修改操作。

下面舉個例子:

Unique 指標

Unique 指標是 C++11 版本的智慧指標類。

一旦你用 unique_ptr 關鍵字定義了一個物件,那麼下列事件只要發生一個,物件就會被銷燬並釋放記憶體:

  • unique_ptr 管理的物件被銷燬。
  • unique_ptr 管理的物件通過賦值操作符指向另一個指標,或呼叫了reset()方法。

對於不想了解太多細節的使用者來說,這就意味著如果你使用了 unique 指標的語義,那麼在跳出作用域之前,你就不用手動回收物件的記憶體了

以前,我們需要這麼寫程式碼:

然後在程式的最後你一定要記得釋放記憶體:

否則你可就造成記憶體洩露了。而現在,

當 obj 跳出作用域範圍之外的時候,記憶體將會被自動回收。

static_assert

static_assert 簡單說就是一個在編譯期執行的斷言。例如,你可以這麼做:

假設由於系統的原因造成了上述的邏輯判斷的失敗,那麼 static_assert 就會斷言失敗。

它的另一種用途,是和 C++ 特徵型別搭配使用。比如:

POD 是指“簡單資料”(Plain Old Data)結構,也就是說,它是一個的類(你可以用struct關鍵字定義,也可以用class關鍵字定義),但沒有建構函式,解構函式和虛成員函式。所以,如果一個愚蠢的菜鳥程式設計師企圖給這種型別增加建構函式的話,static_assert 就會在編譯的時候阻止這種行為,並報錯。這對程式碼維護來說可是非常有用的。

當然 C++ 還有很多有用的特性,我希望在以後的文章中能給大家介紹更多。謝謝大家的關注!

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

C++11 的 10 個實用特性(上)

相關文章