深入理解C++11筆記

本文列出C++11的部分特性以及注意點與用途普气。

1. nullptr

  1. 為了解決的問題是:
void  func(int);
void func(int *);
func(NULL);  //這個函數(shù)調(diào)用會調(diào)用參數(shù)是int的版本谜疤;
  1. (1)nullptr的特點是可以隱式的轉(zhuǎn)化為任意指針類型(比如nullptr當做函數(shù)參數(shù)),但是不可以轉(zhuǎn)化為其他任何類型现诀,包括bool類型(if(nullptr)不允許)夷磕,reinterpret_cast強制轉(zhuǎn)化也不被允許。
    (2)nullptr本質(zhì)是一個編譯期的常量仔沿,換句話說坐桩,其是一個右值,大小與指針一樣大(sizeof(nullptr) == sizeof((void*)0))封锉,是先有的nullptr绵跷,然后定義的nullptr_t
#define decltype(nullptr) nullptr_t

2. =default與=delete

1 編譯器為類中默認生成的成員函數(shù)有六個:

默認構(gòu)造函數(shù)
析構(gòu)函數(shù)
拷貝構(gòu)造函數(shù)
拷貝賦值函數(shù)
移動構(gòu)造函數(shù)
移動賦值函數(shù)

2 使用=default的好處
對定義了非默認構(gòu)造函數(shù)的類的默認構(gòu)造函數(shù)使用=default膘螟,可以使得類還有可能是POD類型。
POD類型的解釋抖坪,維基百科這樣說:

可見萍鲸,POD類類型就是指class闷叉、struct擦俐、union,且不具有用戶定義的構(gòu)造函數(shù)握侧、析構(gòu)函數(shù)蚯瞧、拷貝算子、賦值算子品擎;不具有繼承關(guān)系埋合,因此沒有基類;不具有虛函數(shù)萄传,所以就沒有虛表甚颂;非靜態(tài)數(shù)據(jù)成員沒有私有或保護屬性的、沒有引用類型的秀菱、沒有非POD類類型的(即嵌套類都必須是POD)振诬、沒有指針到成員類型的(因為這個類型內(nèi)含了this指針)。

POD類型的好處是:

  1. 與C語言的struct的內(nèi)存布局相同衍菱,所以可以和C語言結(jié)構(gòu)體交互使用赶么;
  1. 是拷貝不變的(trivially copyable)的class,可以使用memcpy脊串, memmove不改變它的語義辫呻。拷貝的時候調(diào)用這些函數(shù)是更快的琼锋。

使用上:

  1. 《STL源碼分析》中介紹了SGI STL用到的__type_traits放闺,大量的構(gòu)造函數(shù)和析構(gòu)函數(shù)在調(diào)用前會先根據(jù)__type_traits判斷一下是否存在trival的構(gòu)造函數(shù)和析構(gòu)函數(shù),如果是的話缕坎,就不進行循環(huán)怖侦,否則就需要進行。但使用這個的前提是用戶在自定義類中需要定義__type_traits中用到的類型的typedef念赶。
  1. C++11中支持了std::is_pod础钠,即不需要用戶在類中定義出來很多typedef,就可以判斷出是否是POD類型叉谜。

另:

std::is_pod的返回值是constexpr類型旗吁,意思是這個函數(shù)的調(diào)用結(jié)果在編譯期就可以得到,不會等到運行期才執(zhí)行停局。

3 使用=delete的好處

  1. 可以很方便地對編譯器自動生成拷貝操作符或者拷貝構(gòu)造等行為提供禁止很钓,不需要使用私有化這些函數(shù)或者將這些函數(shù)放到父類中設(shè)置為私有并不提供定義的方式來處理了香府。
  1. 可以禁止隱式的類型轉(zhuǎn)化,包括類的成員函數(shù)码倦,也包括全局的函數(shù)企孩。
void func(int);
void func(char) = delete;    //此時就是禁止char隱式轉(zhuǎn)化為int;
  1. 可以實現(xiàn)禁止在堆中或者棧中分配內(nèi)存的操作
void* operator new(std::size_t) = delete;  //禁止在堆中分配內(nèi)存袁稽;
~NoStackAlloc() = delete;      //禁止在棧中分配內(nèi)存勿璃。(棧中的會自動調(diào)用析構(gòu),new出的需要人為delete才調(diào)用)

3. lambda函數(shù)

1 lambda函數(shù)可以在函數(shù)邏輯不是很復(fù)雜的情況下代替函數(shù)指針與仿函數(shù)的使用推汽。其行為類似于一個函數(shù)內(nèi)定義函數(shù)补疑。

2 lambda相對于函數(shù)指針的好處

  1. 函數(shù)指針默認不是inline的,lambda默認是inline的歹撒;
  2. 仿函數(shù)針對函數(shù)指針的好處就是存在初始狀態(tài)莲组,lambda也可以通過捕獲參數(shù)的方式來得到初始狀態(tài)。

lambda除了比仿函數(shù)要簡單暖夭,但缺點是:

lambda所能捕獲的參數(shù)只有父函數(shù)內(nèi)部的局部變量锹杈,更外層的變量是無法捕獲到的。

3 使用lambda需要注意的的問題

  1. 以值捕獲的情況下迈着,定義該lambda的時候會將捕獲到的變量保存到lambda函數(shù)內(nèi)部竭望,后期在lambda外部改變了被捕獲變量的值,不影響lambda函數(shù)內(nèi)部:
    int a = 10;
    auto lambda = [=]() {return a + 10;};  //定義了之后寥假,a就保存到lambda里面了
    a = 30;        //后期再怎么改
    cout << lambda() << endl;    //輸出也是20市框;
    a = 20;
    cout << lambda() << endl;  //輸出也是20;

原因就是糕韧,lambda的實現(xiàn)原理是枫振,編譯器會在編譯期將其轉(zhuǎn)化為仿函數(shù),所以值以構(gòu)造函數(shù)的方式傳遞了進去就無法再改變了萤彩。

  1. 以引用方式捕獲的時候粪滤,lambda改變了被捕獲的數(shù)據(jù),外部可以感知到雀扶。
    這里涉及到lambda是默認const屬性的杖小,含義是會默認將捕獲進來的變量定義為const類型,而引用類型還可以在里面改變的原因是a所引用的對象沒有變愚墓,變化的只是其值予权。成員變量是引用類型,在const函數(shù)內(nèi)是可以改變其值的浪册,如下:
class D {
public:
    D(int a):d(a) {}
    void change() const {
          d = 10;                  //d是引用類型扫腺,在const函數(shù)中可以被改變
    }
    void print() const {
        cout << d << endl;
    }
private:
    int& d;
};
int main()
{
    int a = 20;
    D d(a);
    d.change();
    d.print();        //結(jié)果輸出的是10;
}
  1. 引用方式捕獲的時候沒有以值捕獲時候(第1點)的那種問題村象。

4. 強枚舉類型

  1. enum有幾個特別的性質(zhì):
  1. enum內(nèi)部定義的常量的作用域會被拓展到enum所在作用域笆环,容易引起沖突攒至;
    當然,將enum的定義放到特定的命名空間中躁劣,或者放到類中定義迫吐,則不會污染全局空間。
  2. 存在于整數(shù)的隱式轉(zhuǎn)換账忘,表現(xiàn)為在比較的時候志膀,可以與整數(shù)做比較,可以與另一個enum對象內(nèi)的常量進行比較而不會報錯闪萄。
  3. enum定義的常量所占空間不是一定的梧却,與編譯器有關(guān)。
  1. 針對以上三個問題败去,提出強枚舉類型,在enum于類名之間加上class烈拒,也就對應(yīng)有如下好處:
  1. 合適的常量作用域圆裕,內(nèi)部常量必須通過enum類名來訪問,作用域不再是全局荆几。(enum class想要正常使用的話吓妆,必須有一個名字)
  2. 不能進行隱式轉(zhuǎn)換,但是可以進行顯示轉(zhuǎn)換吨铸;(也是每個常量對應(yīng)一個整數(shù)行拢,但是當做整數(shù)用時必須顯示轉(zhuǎn)化)
  3. 保存常量的數(shù)據(jù)結(jié)構(gòu)可以指定,在enum class name : type的方式指定诞吱,這樣就解決了常量所占空間不一致的問題舟奠。

5. 智能指針與內(nèi)存管理

  1. 幾個智能指針
  1. auto_ptr,C++11之前就有的房维,允許拷貝沼瘫,但是拷貝之后指針所有權(quán)易主;
  2. unique_ptr咙俩,也是只有一個unique_ptr可以擁有這個指針(內(nèi)存資源)耿戚,實現(xiàn)的方法是,=delete掉了拷貝構(gòu)造和拷貝運算符重載阿趁,但是定義了移動構(gòu)造函數(shù)和移動運算符重載膜蛔;
  3. shared_ptr則是可以有多個shared_ptr擁有這個內(nèi)存資源,采用的是引用計數(shù)的方式脖阵,但是會有循環(huán)引用的問題皂股;
  4. weak_ptr則是和shared_ptr搭配使用,可以認為其僅僅就是查詢shared_ptr管理的內(nèi)存的狀態(tài)独撇,比如引用計數(shù)是多少屑墨,釋放沒有躁锁,里面的值是什么,不占有這個資源(引用計數(shù)不加1)卵史,但是也可以查看狀態(tài)信息战转。
  1. shared_ptr存在循環(huán)引用的問題無法解決,可以的解決方式是:

采用基于跟蹤處理的垃圾回收器:
跟蹤是:從當前正在使用的對象(可能很多)開始以躯,找到活的對象槐秧,標記一下;
清除:將未被標記的對象釋放忧设;(存在內(nèi)存碎片)
整理:是將被標記的對象左對齊移動刁标;(存在移動的代價)
拷貝:將活的對象拷貝到另一個空間:TO空間,然后釋放FROM空間址晕,下次FROM與TO空間的用途反過來膀懈。(利用率低且需要移動)

  1. C++11中最小垃圾回收支持
    由于指針的靈活性,導(dǎo)致垃圾回收器實現(xiàn)起來相當困難,比如指針的移動等,解決辦法可以是投储,由用戶來將移動后的指針指向的空間標記為不要清除函喉。

6. sizeof的拓展

sizeof可以用于類的成員變量了:

struct AAA {
    int a;  //public的才可以。
};
//使用上,需要使用類作用域標識符
cout << sizeof(AAA::a) << endl;

7. friend的拓展

friend聲明的類名可以不用加class了。

template<class T> struct AAA {
    friend T;       //如果T是基本類型,該句會被忽略掉
    int a;
};

friend的一個用途是用于測試疑苫,測試類聲明為被測試類的friend,這樣就可以測試私有成員函數(shù)了纷责。friend被拓展后捍掺,就可以當做這個用途。

8. 新引入的final關(guān)鍵字和override關(guān)鍵字

  1. 說明一個現(xiàn)象:
class AAA {
public:
    virtual void func() {
        cout << "AAA" << endl;
    }
};
class BBB : public AAA{
public:
   void func() {
        cout << "BBB" << endl;
    }
};
class CCC :public BBB{
public:
    void func() {
        cout << "CCC" << endl;
    }
};
//結(jié)論是輸出:CCC碰逸,即不論中間有沒有缺少virtual的乡小,只要父類指針有(AAA有),就可以找到正確的對象(CCC)饵史。(不會經(jīng)由BBB)

final的作用是禁止子類重寫函數(shù)(override);
override的作用是告訴編譯器我在重寫满钟,幫我檢查;
使用方法上,final和override是一樣的胳喷,都是在函數(shù)參數(shù)后邊湃番。

9. 名字查找規(guī)則引起的問題

名字查找規(guī)則,當調(diào)用一個類成員函數(shù)時吭露,其會當前類尋找吠撮,如果找到了,就不再向下尋找了讲竿,這個找到泥兰,是找到的名字弄屡,不包括參數(shù);所以當存在子類和父類的函數(shù)重載時鞋诗,通過子類對象是無法調(diào)用父類那個版本的函數(shù)的膀捷。

class AAA {
public:
    void func() {
        cout << "AAA" << endl;
    }
};

class BBB : public AAA{
public:
   void func(int a) {
        cout << "BBB" << endl;
    }
};

//通過如下方式調(diào)用func會報錯
    BBB b;
    b.func();

非指針或者引用的方式調(diào)用,在找到BBB中的func就不再尋找AAA中的了削彬,導(dǎo)致參數(shù)數(shù)量不匹配報錯全庸。
解決辦法是使用using關(guān)鍵字,可以繼承父類中的同名方法:

class AAA {
public:
    void func() {
        cout << "AAA" << endl;
    }
};

class BBB : public AAA{
public:
    using AAA::func;      //強行拉取融痛,解決名字查找規(guī)則的問題
   void func(int a) {
        cout << "BBB" << endl;
    }
};

using還有一個用途是子類想要繼承父類的構(gòu)造函數(shù)壶笼,也可以使用using AAA::AAA,此時AAA在BBB中就變成了BBB雁刷,免去了BBB為構(gòu)造AAA而寫的一系列轉(zhuǎn)發(fā)構(gòu)造函數(shù)覆劈。

以上還有兩個可能的問題:
(1)多個父類的構(gòu)造函數(shù)沖突如何處理:在子類中顯式定義出沖突的那個構(gòu)造函數(shù);
(2)繼承了父類的安券,子類中還存在成員變量如何賦值:使用成員變量就地初始化墩崩;

10. 委托構(gòu)造函數(shù)(有點水)

含義是,構(gòu)造函數(shù)可以在初始化列表中調(diào)用另一個構(gòu)造函數(shù)侯勉,但調(diào)用后不能再有初始化列表。這樣可以避免很多重復(fù)的定義铝阐。
一個用途是址貌,被調(diào)用的構(gòu)造函數(shù)被聲明成template時,可以實現(xiàn)模板構(gòu)造函數(shù)徘键。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末练对,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吹害,更是在濱河造成了極大的恐慌螟凭,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件它呀,死亡現(xiàn)場離奇詭異螺男,居然都是意外死亡,警方通過查閱死者的電腦和手機纵穿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門下隧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谓媒,你說我怎么就攤上這事淆院。” “怎么了句惯?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵土辩,是天一觀的道長支救。 經(jīng)常有香客問我,道長拷淘,這世上最難降的妖魔是什么各墨? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮辕棚,結(jié)果婚禮上欲主,老公的妹妹穿的比我還像新娘。我一直安慰自己逝嚎,他們只是感情好扁瓢,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著补君,像睡著了一般引几。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挽铁,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天伟桅,我揣著相機與錄音,去河邊找鬼叽掘。 笑死楣铁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的更扁。 我是一名探鬼主播盖腕,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浓镜!你這毒婦竟也來了溃列?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤膛薛,失蹤者是張志新(化名)和其女友劉穎听隐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哄啄,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡雅任,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了增淹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椿访。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虑润,靈堂內(nèi)的尸體忽然破棺而出成玫,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布哭当,位于F島的核電站猪腕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钦勘。R本人自食惡果不足惜陋葡,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望彻采。 院中可真熱鬧腐缤,春花似錦、人聲如沸肛响。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽特笋。三九已至剃浇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猎物,已是汗流浹背虎囚。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蔫磨,地道東北人淘讥。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像堤如,于是被迫代替她去往敵國和親适揉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容