C++11 新特性

C++ 面試中經常會被問到的一個問題是,瞭解哪些 C++11 新特性,下面總結幾條實用的新特性

1. 右值引用

傳統的 C++ 引用(現在稱爲左值引用)使標識符關聯到左值。左值是一個表示數據的表達式(如變量名或解除引用的指針)。C++11 新增了右值引用,使用 && 表示。右值則包括字面常量、諸如 x + y 表達式以及返回值的函數。記住一點,左值與右值的根本區別在於能否獲取內存地址,而能否賦值不是區分的依據。

這裏簡要總結一下引用與指針的區別。

兩者都是與地址相關的概念。引用是變量的別名,而指針則是變量的地址。

區別入下:

  • 指針是一個實體(分配內存),而引用僅是個別名;
  • 引用只能在定義時被初始化一次,之後不可變;指針可變;引用“從一而終”,指針可以“見異思遷”;
  • 引用沒有const,指針有const,const的指針不可變;
  • 引用不能爲空,指針可以爲空;
  • “sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身的大小;

從上面可以看出引用更接近 const 指針。

引入右值引用的主要目的之一是實現移動語義,下面展開來談

2. 移動語句

爲方便理解移動語句,考慮下面的示例

vector<string> allcpas(const vector<string> &vs)
{
    vector<string> temp;
    // 將 vs 複製給 temp
    return temp;
}
vector<string> vstr;
// vstr 是包含 20000 個 string 的向量,每個元素有 1000 個字符
vector<string> vstr_copy1(vstr);
vector<string> vstr_copy2(allcps(vstr));    // #2

對語句# 2, allcps 將返回值 temp 複製給臨時形參變量,再將該形參複製給 vstr_copy2 。編譯器對 vstr 複製了兩次。這樣顯然很消耗資源。如果將對數據的所有權直接轉讓給 vstr_copy2 ,顯然會更好,對此我們只需要實現 vstr_copy2移動構造函數,在函數內部將調整臨時變量的所有權,從而避免一次無意義的複製。移動語義實際上避免了移動原始數據,而只是修改了記錄。

3. 基於範圍的 for 循環

對於內置數組已經包含 begin()end() 的類和 STL 容器,基於範圍的 for 循環可以簡化爲它們編寫循環的工作。這種循環對數組或容器中的每個元素執行指定的操作:

std::vector<int> vi(6);
for (auto &x : vi)
    x = std::rand()

x 依次爲 vi 中的每個元素的引用,從而實現了對數組每個元素的修改。

4. 智能指針

智能指針的出現很自然,其行爲類似於指針的類對象,可以在離開對象週期使自動析構函數,釋放動態申請的內存。

模板 auto_ptr 是 c++98 提供的解決方案,C++11 已將其擯棄,並提供了 unique_ptr shared_ptr 兩種解決方案。

智能指針很多方面都類似於常規指針。例如,如果 ps 是一個智能指針對象,則可以對它執行解除引用操作(*ps)、用它來訪問結構成員,將他賦值給相同類型的常規指針。將智能指針對象賦值給對另一個同類型的智能指針對象,將引起一個問題。看下面例子:

auto_ptr<string> ps (new string("I reigned lonely as a cloud."));
auto_ptr<string> vocation;
vocation = ps;

兩個指針指向同一塊內存,會造成程序試圖刪除同一個對象兩次。避免這種問題,有如下思路:

  • 建立所有權的概念,對於特定的指針,智能有一個智能指針對象可以擁有它。讓賦值操作轉讓所有權。這就是用於 auto_ptrunique_ptr 的策略
  • 創建智能更高的指針,跟蹤引用計數特定對象的智能指針數。這稱爲引用計數。例如,賦值計數加1,過期時,計數減1。僅當最後一個指針過期時,才調用 delete。這是 shared_ptr 採用的策略
發佈了155 篇原創文章 · 獲贊 91 · 訪問量 73萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章