C++常見問題

1. 類的靜態(tài)成員和非靜態(tài)成員區(qū)別是:

類的靜態(tài)成員(變量和方法)屬于類本身,在類加載的時候就會分配內(nèi)存池户,可以通過類名直接去訪問咏雌;非靜態(tài)成員(變量和方法)屬于類的對象校焦,所以只有在類的對象產(chǎn)生(創(chuàng)建類的實例)時才會分配內(nèi)存,然后通過類的對象(實例)去訪問氛雪。
所以類的靜態(tài)函數(shù)無法直接訪問普通成員變量耸成,因為類實例化之前, 成員變量還不存在井氢。
當(dāng)調(diào)用一個對象的非靜態(tài)成員函數(shù)時,會把對象的起始地址賦給this指針骗卜,而靜態(tài)成員函數(shù)不屬于某一對象左胞,屬于類本身。
所以非靜態(tài)成員函數(shù)有this指針遍烦,而靜態(tài)靜態(tài)成員函數(shù)沒有this指針躺枕。

2.靜態(tài)全局變量和靜態(tài)局部變量
  • 全局靜態(tài)變量存在靜態(tài)存儲區(qū),在整個程序運行期間一直存在拐云。
    作用域:全局靜態(tài)變量在聲明他的文件之外是不可見的叉瘩,準確地說是從定義之處開始,到文件結(jié)尾薇缅。

  • 局部靜態(tài)變量存在靜態(tài)存儲區(qū)
    作用域:作用域仍為局部作用域攒磨,當(dāng)定義它的函數(shù)或者語句塊結(jié)束的時候娩缰,作用域結(jié)束拼坎。但是當(dāng)局部靜態(tài)變量離開作用域后狱掂,并沒有銷毀,而是仍然駐留在內(nèi)存當(dāng)中趋惨,只不過我們不能再對它進行訪問器虾,直到該函數(shù)再次被調(diào)用,并且值不變兆沙;

  1. string本身就會判斷最后一個字節(jié)是否為多余的半個漢字,是的話不輸出該字節(jié)千扔。 如 字符串“我ABC汗DEF”库正,截取6個字節(jié)是“我ABC” , 截取7個字節(jié)是“我ABC汗”。
4. malloc和new的區(qū)別

1) malloc 返回的類型是void* 需要強制類型轉(zhuǎn)換龙誊,new 返回的就是需要的類型喷楣;
2)malloc 返回的內(nèi)存空間初值是不確定的,new返回的是初始化過得
3)malloc是函數(shù) new是運算符
4)new內(nèi)存分配失敗時铣焊,會拋出bac_alloc異常曲伊,它不會返回NULL;malloc分配內(nèi)存失敗時返回NULL。
5)new操作符從自由存儲區(qū)(free store)上為對象動態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動態(tài)分配內(nèi)存婿屹。
  自由存儲區(qū)是C++基于new操作符的一個抽象概念,凡是通過new操作符進行內(nèi)存申請届腐,該內(nèi)存即為自由存儲區(qū)蜂奸。而堆是操作系統(tǒng)中的術(shù)語,是操作系統(tǒng)所維護的一塊特殊內(nèi)存围详,用于程序的內(nèi)存動態(tài)分配祖屏,C語言使用malloc從堆上分配內(nèi)存,使用free釋放已分配的對應(yīng)內(nèi)存袁勺。
  那么自由存儲區(qū)是否能夠是堆(問題等價于new是否能在堆上動態(tài)分配內(nèi)存)期丰,這取決于operator new 的實現(xiàn)細節(jié)。自由存儲區(qū)不僅可以是堆钝荡,還可以是靜態(tài)存儲區(qū),這都看operator new在哪里為對象分配內(nèi)存几晤。
6)使用malloc分配的內(nèi)存后植阴,如果在使用過程中發(fā)現(xiàn)內(nèi)存不足,可以使用realloc函數(shù)進行內(nèi)存重新分配實現(xiàn)內(nèi)存的擴充憾朴。realloc先判斷當(dāng)前的指針所指內(nèi)存是否有足夠的連續(xù)空間喷鸽,如果有,原地擴大可分配的內(nèi)存地址砾省,并且返回原來的地址指針;如果空間不夠编兄,先按照新指定的大小分配空間,將原有數(shù)據(jù)從頭到尾拷貝到新分配的內(nèi)存區(qū)域揣苏,而后釋放原來的內(nèi)存區(qū)域件舵。
new沒有這樣直觀的配套設(shè)施來擴充內(nèi)存。new在內(nèi)存分配時如果發(fā)生內(nèi)存不足坑质,在拋出異常之前个少,可以使用由程序員提供的處理例程,被稱作new_handle;

------malloc函數(shù)工作機制--------------------------------------------------------------------------------
malloc函數(shù)的實質(zhì)體現(xiàn)在壳澳,它有一個將可用的內(nèi)存塊連接為一個長長的列表的所謂空閑[鏈表茫经。調(diào)用malloc函數(shù)時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內(nèi)存塊抹镊。然后荤傲,將該內(nèi)存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節(jié))终佛。接下來雾家,將分配給用戶的那塊內(nèi)存?zhèn)鹘o用戶,并將剩下的那塊(如果有的話)返回到連接表上牙捉。調(diào)用free函數(shù)時,它將用戶釋放的內(nèi)存塊連接到空閑鏈上芬位。到最后霜浴,空閑鏈會被切成很多的小內(nèi)存片段,如果這時用戶申請一個大的內(nèi)存片段阴孟,那么空閑鏈上可能沒有可以滿足用戶要求的片段了永丝。于是箭养,malloc函數(shù)請求延時,并開始在空閑鏈上翻箱倒柜地檢查各內(nèi)存片段喝检,對它們進行整理撼泛,將相鄰的小空閑塊合并成較大的內(nèi)存塊。如果無法獲得符合要求的內(nèi)存塊损俭,malloc函數(shù)會返回NULL指針潘酗,因此在調(diào)用malloc動態(tài)申請內(nèi)存塊時,一定要進行返回值的判斷琐脏。
malloc底層實現(xiàn)原理


5. 小技巧

為了節(jié)省內(nèi)存缸兔,結(jié)構(gòu)體可以設(shè)置為union的,union中多個變量值阅签,同時只有一個有用蝎抽。
union共享內(nèi)存地址 可以用union判斷當(dāng)前系統(tǒng)以大端還是小端存儲 示例如下:

union MyUnion
{
    short a;
    char b[sizeof(short)];
};
/*union共享一塊內(nèi)存路克,以達到節(jié)省內(nèi)存的用途精算;
*所以當(dāng)test.a被賦初值時碎连,test.b也是同一塊內(nèi)存區(qū)域,可以以char類型讀取
*所以就可以判斷其是大端還是小端廉嚼。
*/
int main()
{
    MyUnion test;
    test.a = 0x0102;
    if (test.b[0] == 0x01 && test.b[1] == 0x02)
        cout << "small endian" << endl;
    else if (test.b[0] == 0x02 && test.b[1] == 0x01)
        cout << "big endian" << endl;
    else
        cout << "UNknow" << endl;
        
    return 0;
}
6. struct和class的區(qū)別:

struct默認成員變量默認是public倒戏,class 是private的,C++的class是由struct擴展而來的傍念,在C語言中struct是不可以定義成員函數(shù)的葛闷,但在C++中擴展了struct的功能,也可以定義成員函數(shù)阳仔。

7. 對象的存儲空間計算

權(quán)威的結(jié)論是:非靜態(tài)成員變量總和加上為了CPU計算作出的數(shù)據(jù)對齊處理和支持虛函數(shù)所產(chǎn)生的負擔(dān)治笨。
1). C++中每個空類型的實例占1Byte空間;
2). 靜態(tài)數(shù)據(jù)成員不占對象的內(nèi)存空間旷赖;
3). 成員函數(shù)不占空間;
4). 構(gòu)造函數(shù)和析構(gòu)函數(shù)不占空間稚照;
5). 類中有一個或多個虛函數(shù),則需要計算一個指向虛函數(shù)表的指針所需的空間边坤;(編譯器為了支持虛函數(shù)助析,需要一個指向虛函數(shù)表的指針,64位機器占8Byte)
每個對象所占用的存儲空間只是該對象的非靜態(tài)數(shù)據(jù)成員的總和,不包括成員函數(shù)和靜態(tài)數(shù)據(jù)成員锈玉,函數(shù)代碼是存在對象空間之外的

8. this指針

this指針是指向本類對象的指針义起,它的值是當(dāng)前被調(diào)用的成員函數(shù)所在的對象的起始地址默终。

class A
{
  int x;
  int y;
  int z;
};
A a;
int sum=a.x+a.y+a.z;
//這里相當(dāng)于this.x+this.y+this.z;

this指針有以下特點:
1).只能在成員函數(shù)中使用,在全局函數(shù)两疚、靜態(tài)成員函數(shù)中都不能使用含滴;
2).this指針在成員函數(shù)開始前構(gòu)造,并在成員函數(shù)的結(jié)束后清除;
3).this指針會因編譯器不同而具有不同的存儲位置鞋吉,可能是棧、寄存器或者全局變量谓着;
4).this是類的指針赊锚;
5).this指針只有在成員函數(shù)中才有定義,所以獲得一個對象后耸袜,不能通過對象使用this指針牲平,所以也就無法知道一個對象指針的位置。不過蜈抓,可以在成員函數(shù)中指定this指針的位置昂儒;
6).普通的類函數(shù)都不會擦混構(gòu)建一個函數(shù)表來保存函數(shù)指針,只有虛函數(shù)才會被放到函數(shù)表中腊嗡;

  1. 對基類成員和子對象成員的初始化必須在成員初始化列表中進行,新增成員的初始化既可以在成員初始化列表中進行屈呕,也可以在構(gòu)造函數(shù)體中進行棺亭。

派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序
1).如果有多個基類镶摘,則構(gòu)造函數(shù)的順序是某類在類派生表中出現(xiàn)的順序,而不是他們在成員初始化表中的順序碌冶;
2).如果有多個成員類對象涝缝,則構(gòu)造函數(shù)的順序是對象在類中被聲明的順序扑庞,而不是他們出現(xiàn)在成員初始化列表中的順序;
3).首先調(diào)用派生類的析構(gòu)函數(shù)拒逮,其次在調(diào)用成員類對象的析構(gòu)函數(shù)滩援,最后調(diào)用基類的析構(gòu)函數(shù);
析構(gòu)函數(shù)調(diào)用情況
1).對象生命周期被銷毀時租悄;
2).delete指向?qū)ο蟮闹羔槙r恩袱,或者delete指向?qū)ο蟮幕愵愋椭羔槪浠愄摌?gòu)函數(shù)是虛函數(shù)時外傅;
3).對象i是o的成員俩檬,o的析構(gòu)函數(shù)被調(diào)用時,對象i的析構(gòu)函數(shù)也被調(diào)用技竟;

10. 多態(tài)

多態(tài)性是指不同功能的函數(shù)可以用同一個函數(shù)名屈藐,這樣就可以用一個函數(shù)名調(diào)用不同內(nèi)容的函數(shù)。意思是:向不同的對象發(fā)送同一個消息搓扯,不同的對象在接收時產(chǎn)生不同的行為

11. vector

reserve()是為了減少重新分配內(nèi)存的次數(shù)锨推,提升使用效率;
size()返回的是容器元素的真實大凶狄沾鳄;
resize()是修改容器內(nèi)元素數(shù)量的大小译荞,大則刪除,小則擴充吞歼;
capacity()是容器在已經(jīng)分配的內(nèi)存中可以容納多少元素浆熔,反應(yīng)此時的真實容量桥帆,不是元素個數(shù)老虫。

12. 函數(shù)對象

函數(shù)對象即調(diào)用操作符的類,其對象稱為函數(shù)對象祈匙,他們是行為類似函數(shù)的對象夺欲。表現(xiàn)出一個函數(shù)的特征,就是通過“對象名+(參數(shù)列表)”的方式使用一個類伞剑,其實質(zhì)是對operator()操作符的重載市埋。


image.png

其中

struct CmpByKeyLength
{
      bool  operator() (const string& k1, const string& k2)
      {
           return k1.length() < k2.length();
      }
}

就是一個函數(shù)對象,傳到map褐着,vector托呕,set等容器里面,就可以實現(xiàn)自定義的排序順序谴餐。

12. C++編譯與鏈接
  1. 預(yù)處理:主要處理源代碼中以“#”開始的預(yù)編譯指令呆抑。
    比如刪除#define鹊碍,#if,#endif公罕,處理#include指令耀销,將包含的文件加入進來,者是個遞歸的過程罐柳;還有過濾注釋狰住,添加行號和文件名標識催植;
  2. 編譯:把預(yù)處理完的文件進行一系列的詞法分析、語法分析伦忠、語義分析以及優(yōu)化后產(chǎn)生相應(yīng)的匯編代碼文件稿辙。
    編譯的過程一般分為六步:掃描(詞法分析)、語法分析未桥、語義分析、源代碼優(yōu)化舌菜、代碼生成和目標代碼優(yōu)化亦镶。
    image.png
  3. 鏈接:就是把各個模塊之間相互引用的部分都處理好缤骨,使得各個模塊之間能夠正確的銜接。
    鏈接過程主要包括地址和空間分配精拟、符號決議和重定位等這些步驟虱歪。
    image.png

    靜態(tài)庫和動態(tài)庫:
    1)當(dāng)某個程序要調(diào)用某個動態(tài)鏈接庫函數(shù)時笋鄙,操作系統(tǒng)首先會查看所有正在運行的程序,看內(nèi)存里是否有此庫函數(shù)的拷貝践美,如果有找岖,可以共享那一個拷貝宣增,只有沒有時才鏈接載入矛缨,這樣節(jié)省了系統(tǒng)的內(nèi)存資源箕昭;而靜態(tài)庫不同,如果有程序要調(diào)用某個靜態(tài)庫函數(shù)時泌霍,則每個程序都要將這個庫函數(shù)拷貝到自己的代碼中去,這將占用更大的內(nèi)存資源蟹地;
    2)將一些程序升級變得簡單藤为,只要動態(tài)庫提供給該程序的接口沒變,只要重新用新生成的動態(tài)庫替換原來就可以了分别;
    3)動態(tài)鏈接庫本著“有需求才調(diào)入”的原則存淫,可以大大節(jié)省系統(tǒng)資源桅咆;
    4)靜態(tài)庫在編譯的時候就會被裝載到程序中去,所以執(zhí)行時使用靜態(tài)庫速度更快刽脖。
13. linux程序內(nèi)存布局空間

image.png

image.png

初始化數(shù)據(jù)段也叫常量區(qū)曲管,存放一般的常量硕糊、字符串常量等简十。這塊內(nèi)存只有讀取權(quán)限,沒有寫入權(quán)限恢恼,因此它們的值在程序運行期間不能改變胰默。
未初始化數(shù)據(jù)段也叫全局數(shù)據(jù)區(qū),存放全局變量漏隐、靜態(tài)變量等奴迅。這塊內(nèi)存有讀寫權(quán)限,因此它們的值在程序運行期間可以任意改變扁耐。

堆浩村、棧的區(qū)別
1)申請方式不同:
棧:由系統(tǒng)自動分配;
堆:程序員自己申請酿矢;
2)申請后系統(tǒng)的響應(yīng)不同:
棧:主要棧的剩余空間大于所申請的空間怎燥,系統(tǒng)就會提供內(nèi)存铐姚,否則報異常;
堆:操作系統(tǒng)有一個記錄空閑地址的鏈表之众,當(dāng)系統(tǒng)收到程序的申請時依许,會遍歷該鏈表峭跳。尋找第一個大于申請空間的堆節(jié)點;
3)申請大小的限制:
棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu)悬襟,是一塊連續(xù)的內(nèi)存區(qū)域拯刁;棧頂位置和棧的容量是系統(tǒng)預(yù)先設(shè)定好的。在linux下可以使用ulimit -a查看棧大小的限制割捅,通過ulimit -s修改棧的大小巫糙;
堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域醉锄;
4)申請效率不同:
棧由系統(tǒng)自動分配恳不,速度較快;但程序員無法控制规求;
堆是由new分配的內(nèi)存卵惦,一般速度較慢沮尿,容易產(chǎn)生內(nèi)存碎片,但用起來方便赴邻;
5)存儲內(nèi)容不同:
在函數(shù)調(diào)用時啡捶,第一個進棧的是主函數(shù)中后的下一條指令的地址届慈,然后是函數(shù)的各個參數(shù),大多數(shù)編譯器臊泌,參數(shù)由右往左入棧揍拆,然后是函數(shù)的局部變量;當(dāng)本次調(diào)用結(jié)束后播揪,局部變量先出棧猪狈,然后是參數(shù)辩恼,最后棧頂指針指向最開始存的地址谓形。
堆一般是在堆得頭部用一個字節(jié)存放堆得大小寒跳。堆中具體內(nèi)容由程序員安排竹椒。

14. char 類型

char是C/C++整型數(shù)據(jù)中比較古怪的一個胸完,其它的如int/long/short等不指定signed/unsigned時都默認是signed,但char在標準中是unsigned

  • uint_8與u8征冷、uint16_t與u16誓琼、unit_32與u32沒有區(qū)別
    分別是 unsigned char unsigned int unsigned long int的不同寫法
  • unsigned char是無符號字節(jié)型腹侣,char類型變量的大小通常為1個字節(jié)(1字節(jié)=8個位),且屬于整型饺律。
15. emplace_back 與 push_back的區(qū)別

c++開發(fā)中我們會經(jīng)常用到插入操作對stl的各種容器進行操作复濒,比如vector,map,set等乒省。在引入右值引用,轉(zhuǎn)移構(gòu)造函數(shù)砸泛,轉(zhuǎn)移復(fù)制運算符之前唇礁,通常使用push_back()向容器中加入一個右值元素(臨時對象)時惨篱,首先會調(diào)用構(gòu)造函數(shù)構(gòu)造這個臨時對象,然后需要調(diào)用拷貝構(gòu)造函數(shù)將這個臨時對象放入容器中砸讳。原來的臨時變量釋放。這樣造成的問題就是臨時變量申請資源的浪費。
引入了右值引用陶耍,轉(zhuǎn)移構(gòu)造函數(shù)后烈钞,push_back()右值時就會調(diào)用構(gòu)造函數(shù)和轉(zhuǎn)移構(gòu)造函數(shù);
而c++11 新加的emplace_back馒过,在插入的時候直接構(gòu)造酗钞,就只需要構(gòu)造一次即可砚作,只會調(diào)用一次構(gòu)造函數(shù),相對于push_back的兩次調(diào)用性能更優(yōu)着裹。

16. printf右結(jié)合骇扇,&&優(yōu)先級低面粮,*p++的意義
int a=6, b=9;
printf("%d", a, b);

以上程序中printf右結(jié)合但金,按順序?qū), b壓棧钱磅,然后最后 出棧的是a似枕,所以輸出的結(jié)果是6凿歼;

p++的作用是:先解引用冗恨,獲得p所指向的值掀抹,然后將p++心俗,即p指向下一位。
(
p)++的作用是:解引用揪利,獲得p所指向的值疟位,然后將指向的值自加喘垂,指針并不移動正勒。

17. 四種強制類型轉(zhuǎn)換

static_cast

static_cast用于將一種數(shù)據(jù)類型強制轉(zhuǎn)換為另一種數(shù)據(jù)類型。
它主要有如下幾種用法:
(1)用于類層次結(jié)構(gòu)中基類和派生類之間指針或引用的轉(zhuǎn)換
進行上行轉(zhuǎn)換(把派生類的指針或引用轉(zhuǎn)換成基類表示)是安全的
進行下行轉(zhuǎn)換(把基類的指針或引用轉(zhuǎn)換為派生類表示)尿招,由于沒有動態(tài)類型檢查就谜,所以是不安全的
(2)用于基本數(shù)據(jù)類型之間的轉(zhuǎn)換里覆,如把int轉(zhuǎn)換成char丧荐。這種轉(zhuǎn)換的安全也要開發(fā)人員來保證
(3)把空指針轉(zhuǎn)換成目標類型的空指針
(4)把任何類型的表達式轉(zhuǎn)換為void類型
注意:static_cast不能轉(zhuǎn)換掉expression的const、volitale或者__unaligned屬性喧枷。

dynamic_cast

用法:dynamic_cast<type_id> (expression)

(1)其他三種都是編譯時完成的虹统,dynamic_cast是運行時處理的,運行時要進行類型檢查隧甚。
(2)不能用于內(nèi)置的基本數(shù)據(jù)類型的強制轉(zhuǎn)換车荔。
(3)dynamic_cast轉(zhuǎn)換如果成功的話返回的是指向類的指針或引用,轉(zhuǎn)換失敗的話則會返回NULL忧便。
(4)使用dynamic_cast進行轉(zhuǎn)換的,基類中一定要有虛函數(shù)帽借,否則編譯不通過珠增。

  • 基類中需要檢測有虛函數(shù)的原因:類中存在虛函數(shù)超歌,就說明它有想要讓基類指針或引用指向派生類對象的情況,此時轉(zhuǎn)換才有意義蒂教。
  • 這是由于運行時類型檢查需要運行時類型信息巍举,而這個信息存儲在類的虛函數(shù)表(關(guān)于虛函數(shù)表的概念,詳細可見<Inside c++ object model>)中凝垛,**
  • 只有定義了虛函數(shù)的類才有虛函數(shù)表禀综。**

(5)在類的轉(zhuǎn)換時,在類層次間進行上行轉(zhuǎn)換時苔严,dynamic_cast和static_cast的效果是一樣的。在進行下行轉(zhuǎn)換時孤澎,dynamic_cast具有類型檢查的功能届氢,比static_cast更安全。

  • 向上轉(zhuǎn)換覆旭,即為子類指針指向父類指針(一般不會出問題)退子;向下轉(zhuǎn)換,即將父類指針轉(zhuǎn)化子類指針型将。
  • 向下轉(zhuǎn)換的成功與否還與將要轉(zhuǎn)換的類型有關(guān)寂祥,即要轉(zhuǎn)換的指針指向的對象的實際類型與轉(zhuǎn)換以后的對象類型一定要相同,否則轉(zhuǎn)換失敗七兜。
  • 在C++中丸凭,編譯期的類型轉(zhuǎn)換有可能會在運行時出現(xiàn)錯誤,特別是涉及到類對象的指針或引用操作時腕铸,更容易產(chǎn)生錯誤惜犀。Dynamic_cast操作符則可以在運行期對可能產(chǎn)生問題的類型轉(zhuǎn)換進行測試。

const_cast

用法:const_cast<type_id> (expression)
用于強制去掉不能被修改的常數(shù)特性狠裹,但需要特別注意的是const_cast不是用于去除變量的常量性虽界,而是去除指向常數(shù)對象的指針或引用的常量性,其去除常量性的對象必須為指針或引用涛菠。
該運算符用來修改類型的const或volatile屬性莉御。除了const 或volatile修飾之外, type_id和expression的類型是一樣的俗冻。

  • 常量指針被轉(zhuǎn)化成非常量指針礁叔,并且仍然指向原來的對象;
  • 常量引用被轉(zhuǎn)換成非常量引用迄薄,并且仍然指向原來的對象晴圾;
  • 常量對象被轉(zhuǎn)換成非常量對象。

reinterpret_cast

用法:reinterpret_cast<type_id> (expression)
主要有三種強制轉(zhuǎn)換用途:改變指針或引用的類型噪奄、將指針或引用轉(zhuǎn)換為一個足夠長度的整形死姚、將整型轉(zhuǎn)換為指針或引用類型人乓。

  • type-id必須是一個指針、引用都毒、算術(shù)類型色罚、函數(shù)指針或者成員指針。
  • 它可以把一個指針轉(zhuǎn)換成一個整數(shù)账劲,也可以把一個整數(shù)轉(zhuǎn)換成一個指針(先把一個指針轉(zhuǎn)換成一個整數(shù)戳护,在把該整數(shù)轉(zhuǎn)換成原類型的指針,還可以得到原先的指針值)瀑焦。
  • 在使用reinterpret_cast強制轉(zhuǎn)換過程僅僅只是比特位的拷貝腌且,因此在使用過程中需要特別謹慎!
18. 右值榛瓮,左值铺董,和移動語義

右值是等號右邊的值,比如常量值是右值
lvalue指在內(nèi)存中占有確定位置的對象禀晓。rvalue指在內(nèi)存中沒有確定位置的對象精续。
左值可以修改,右值不能修改粹懒。
左值持久重付,右值短暫。
移動語義其實可以理解成static_cast()凫乖,將一個左值強轉(zhuǎn)成右值确垫。
使用移動語義的原因是:一般復(fù)制時,需要先復(fù)制一個副本帽芽,也就是復(fù)制出來一個右值森爽,然后用這個副本進行拷貝到目的空間;當(dāng)你使用移動拷貝函數(shù)的時候嚣镜,不需要復(fù)制出來一個副本爬迟,而是直接把原來的左值轉(zhuǎn)化成右值,然后進行復(fù)制菊匿,減少了一個拷貝副本的過程付呕。
參考1 左值,右值與移動
參考2 move的原理跌捆,vector擴容時的操作

19. const用處

1)const修飾變量
const修飾變量徽职,可以使變量具有常屬性,也就是該變量在以后的使用中其值都不能進行改變佩厚。


image

在這里要注意的一點就是const修飾的變量要進行初始化姆钉。

2)const和指針
用const修飾指針有以下幾種情況


image

3)保護函數(shù)參數(shù)不被改變
用const修身函數(shù)的參數(shù),可以保證該參數(shù)的值在函數(shù)內(nèi)部不被改變。
但是一般const修飾的參數(shù)都有哪些呢潮瓶?
一般用引用或者傳地址的方式給函數(shù)傳遞一個參數(shù)陶冷,如果在函數(shù)體內(nèi)對該參數(shù)進行修改,那么就會連實參的值一并進行修改毯辅。

4)const修飾函數(shù)返回值
const修飾函數(shù)的返回值埂伦,防止函數(shù)的返回值被修改


image

但是這里要注意的是,必須也用const修飾的變量來接收這個函數(shù)的返回值思恐。

5)const修飾類成員函數(shù)
const可以修飾類成員函數(shù)沾谜,防止類成員函數(shù)中除了static成員之外的其他成員被修改。


image

6)const修飾類的成員變量
類的成員變量可以分為靜態(tài)的和非靜態(tài)的胀莹,如果const修飾的是靜態(tài)的成員變量基跑,可以在構(gòu)造函數(shù)中對該變量進行初始化;如果const修飾的是靜態(tài)的成員變量描焰,則需要在類外對該變量進行初始化媳否。


image

7)const和#define的區(qū)別
\#define A 10
const int A=10;
上面兩條語句的作用是一樣的,但是后面一條語句可以節(jié)省內(nèi)存空間栈顷,這是為什么呢?
原因在于在程序中多次使用const類型的變量嵌巷,只會在第一次分配內(nèi)存萄凤,但是如果使用#define定義的宏,則每次都會分配內(nèi)存搪哪,這樣看來使用const會節(jié)省很多空間靡努。

8)const和extern
file1.cpp中, const int a;
file2.cpp中, extern int a;//錯誤,無法調(diào)用,
說明const修飾大的變量只能在該程序的本文件中使用,不能在該程序的其他文件中使用晓折。
要想const定義的對象變量能被其他文件調(diào)用,定義時必須使用extern修飾為
extern const int val;

20. map hash_map unordemap

map
頭文件#include<map>
??內(nèi)部數(shù)據(jù)的組織惑朦,基于紅黑樹實現(xiàn),紅黑樹具有自動排序的功能漓概,因此map內(nèi)部所有的數(shù)據(jù)漾月,在任何時候,都是有序的胃珍。

** hash_map**
頭文件#include<hash_map>
基于哈希表梁肿,數(shù)據(jù)插入和查找的時間復(fù)雜度很低,幾乎是常數(shù)時間觅彰,而代價是消耗比較多的內(nèi)存吩蔑。底層實現(xiàn)上,使用一個下標范圍比較大的數(shù)組來存儲元素填抬,形成很多的桶烛芬,利用hash函數(shù)對key進行映射到不同區(qū)域進行保存。

  • 插入操作:得到key -> 通過hash函數(shù)得到hash值 -> 得到桶號(hash值對桶數(shù)求模) -> 存放key和value在桶內(nèi)
  • 取值過程:得到key -> 通過hash函數(shù)得到hash值 -> 得到桶號(hash值對桶數(shù)求模) -> 比較桶內(nèi)元素與key是否相等 -> 取出相等紀錄的value
  • 當(dāng)每個桶內(nèi)只有一個元素時,查找時只進行一次比較赘娄,當(dāng)很多桶都沒有值時仆潮,查詢更快。
  • 用戶可以指定自己的hash函數(shù)與比較函數(shù)擅憔。

unordered_map
頭文件#include<undered_map>
??C++ 11標準中加入了unordered系列的容器鸵闪。unordered_map記錄元素的hash值,根據(jù)hash值判斷元素是否相同暑诸。map相當(dāng)于java中的TreeMap蚌讼,unordered_map相當(dāng)于HashMap。無論從查找个榕、插入上來說篡石,unordered_map的效率都優(yōu)于hash_map,更優(yōu)于map西采;而空間復(fù)雜度方面凰萨,hash_map最低,unordered_map次之械馆,map最大胖眷。
??對于STL里的map容器,count方法與find方法霹崎,都可以用來判斷一個key是否出現(xiàn)珊搀,count統(tǒng)計的是key出現(xiàn)的次數(shù),因此只能為0/1尾菇,而find基于迭代器實現(xiàn)境析,以mp.end()判斷是否找到要求的key。

underordermap 和 hash_map的區(qū)別
hash_map的rehash簡單粗暴派诬,直接就是更新bucket數(shù)目為需要的數(shù)目就行了劳淆,而不會像unordered_map那樣子進行數(shù)量的優(yōu)化。

21 指針和引用的區(qū)別

1) 引用是別名默赂,指針是地址
2) 指針在運行時可以改變所指向的值沛鸵,而引用一旦與某個對象綁定后就不再改變
3) 程序為指針變量分配區(qū)域,而不為引用分配內(nèi)存區(qū)域缆八。
4) 從理論上來說谒臼,對于指針沒有級數(shù)限制,但是引用只有一級耀里。
5) 程序在編譯時分別將指針和引用添加到符號表上蜈缤,符號表上記錄的是變量名及變
量所對應(yīng)地址。指針變量在符號表上對應(yīng)的地址值為指針變量的地址值冯挎,而引用在符號表上對應(yīng)的地址值為引用對象的地址值底哥。符號表生成后就不會再改咙鞍,因此指針可以改變指向的對象(指針變量中的值可以改),而引用對象不能改趾徽。這是使用指針不安全而使用引用安全的主要原因续滋。從某種意義上來說引用可以被認為是不能改變的指針。

參考1 參考2 參考3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孵奶,一起剝皮案震驚了整個濱河市疲酌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌了袁,老刑警劉巖朗恳,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異载绿,居然都是意外死亡粥诫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門崭庸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怀浆,“玉大人,你說我怎么就攤上這事怕享≈瓷模” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵函筋,是天一觀的道長沙合。 經(jīng)常有香客問我,道長驻呐,這世上最難降的妖魔是什么灌诅? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任芳来,我火速辦了婚禮含末,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘即舌。我一直安慰自己佣盒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布顽聂。 她就那樣靜靜地躺著肥惭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪紊搪。 梳的紋絲不亂的頭發(fā)上蜜葱,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音耀石,去河邊找鬼牵囤。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的揭鳞。 我是一名探鬼主播炕贵,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼野崇!你這毒婦竟也來了称开?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤乓梨,失蹤者是張志新(化名)和其女友劉穎鳖轰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體督禽,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡脆霎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狈惫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睛蛛。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胧谈,靈堂內(nèi)的尸體忽然破棺而出忆肾,到底是詐尸還是另有隱情,我是刑警寧澤菱肖,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布客冈,位于F島的核電站,受9級特大地震影響稳强,放射性物質(zhì)發(fā)生泄漏场仲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一退疫、第九天 我趴在偏房一處隱蔽的房頂上張望渠缕。 院中可真熱鬧,春花似錦褒繁、人聲如沸亦鳞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽燕差。三九已至,卻和暖如春坝冕,著一層夾襖步出監(jiān)牢的瞬間徒探,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工喂窟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留测暗,地道東北人吵血。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像偷溺,于是被迫代替她去往敵國和親蹋辅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

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

  • 第一天 一.內(nèi)聯(lián)函數(shù)(inline) 函數(shù)調(diào)用的時候需要建立棧內(nèi)存環(huán)境挫掏,進行參數(shù)傳遞侦另,并產(chǎn)生程序執(zhí)行轉(zhuǎn)移,這些工作...
    陳果123閱讀 1,127評論 0 1
  • 第一章 計算機與C++編程簡介 C++程序6個階段編程 ->預(yù)處理->編譯->連接->裝入->執(zhí)行1.程序在編譯器...
    rogertan30閱讀 3,849評論 0 1
  • ^函數(shù)重載的匹配: 當(dāng)函數(shù)名被重載后尉共,函數(shù)的匹配過程:首先尋找能精確匹配的函數(shù)褒傅,如果未能精確匹配,則嘗試...
    魯大帥閱讀 1,018評論 0 1
  • 幾種語言的特性 匯編程序:將匯編語言源程序翻譯成目標程序編譯程序:將高級語言源程序翻譯成目標程序解釋程序:將高級語...
    囊螢映雪的螢閱讀 2,893評論 1 5
  • 假如生活欺騙了你鸠按,怎么辦礼搁? 假如生活一成不變,怎么辦目尖? 假如在安逸與未知中舉棋不定馒吴,怎么辦? 假如渴望突破又畏手畏...
    夜中深魅閱讀 228評論 0 1