C++學習總結

一些須要知道的基礎知識點:數組

在程序代碼中是經過變量名對內存單元進行存取操做的,可是代碼通過編譯後將變量名轉換爲該變量在內存中的存放地址,對變量值的存取都是經過地址進行的。好比i+j的運算,若是i等於3,j等於4,程序是先根據變量名與地址的對應關係,找到變量i的地址,從第一個地址開始順序讀取四個字節數據放到CPU寄存器中;再找到j的地址,依次讀取四個放到寄存器中,而後經過CPU的加法中斷計算出結果。函數

在低級的彙編語言中都是直接經過地址來訪問內存單元的,而在高級語言中才使用變量名訪問內存單元,C語言做爲高級語言卻提供了經過地址來訪問內存單元的方法,C++也繼承了這一特性。地址能夠形象地稱爲指針,意思是經過指針能找到內存單元,由於本來是經過地址找到內存單元的,因此一個變量的地址稱爲該變量的指針。若是有一個變量專門存放另外一個變量的地址,它就是指針變量。在C++語言中,專門用來存放內存單元地址的變量類型,稱爲指針類型。spa

指針是一種數據類型,一般所說的指針就是指針變量,是專門用來存放地址的變量。而變量的指針說的就是變量在內存中的地址。變量地址在編寫代碼時沒法得到,只有在程序運行時才能夠獲得。指針

指針跟常規的變量爲賦值相同,沒有具體指向的指針不會致使編譯出錯,可是可能會致使難以預料的錯誤,因此一旦定義指針,必定要讓它有一個具體的指向,也就是說要有一個地址賦給它。blog

另外,定義指針變量的時候,跟其餘常規變量爲了區分,要加*號,但其實真正的指針變量是沒有*號的,在使用的時候要注意。繼承

指針進行運算其實就是地址進行運算,指針的加減運算是跟指針的類型有關的,好比int類型的指針加1,地址值並非加1而是加4,由於int類型佔四個字節。內存

※指針還能夠指向空類型void。空類型指針能夠接受任何類型的數據,例如void *p = NULL作用域

這裏有點問題,NULL代替空指針存在二義性,因此後來用nullptr來代替空指針。總之,只要記住nullptr表明空指針就能夠了,而NULL在C++中都把它理解爲0就能夠了。字符串

※const int *p = &i  表示這個指針是指向常量的指針,只能用來「讀」內存數據,沒法經過*p的方式更改內存的內容,即更改變量的值,可是能夠改變自身的地址值,就是指向別的內存地址;編譯器

※int* const p = &i  表示這個指針是一個常量指針,什麼意思呢,覺得指針變量裏存放的是地址,定義爲常量指針的話,說明這個指針變量存放的地址值是不能夠改變的,可是呢,能夠經過*p的方式改變內存的數據;

※const int* const p = &i  表示這個指針是指向常量的常量指針,有點拗口,跟上面的對比,反正就是隻能用來「讀」內存數據,也沒法經過*p的方式更改內存的內容,也沒法改變自身的地址值。

 

指針和一維數組

一維數組和二維數組在內存中的存放結構都是線性的。數組第一元素的地址就是整個數組的存儲首地址,該地址存放在數組名中,看吧,其實數組名就至關於一個指針變量了,裏頭存放的是數組的首地址。訪問數組元素的方式有下標法和指針法。用數組名[i]這個方式能夠訪問數組內容,其實也能夠經過*(a+i)的方式,固然咱們也能夠再單獨定義一個指針變量,將數組的首地址存放到這個指針變量中,固然了,能夠用&a[0]也能夠直接用a即數組名,由於咱們說過了數組名原本就存放的是數組的首地址。

*(p++)至關於a[i++],先對p進行*運算,再使p自增。

指針與二維數組

a[0]是二維數組第一個元素的地址,能夠賦值給一個指針變量。

a表明二維數組的地址,經過指針運算符能夠獲取數組中的元素。

a+n表示第n行的首地址;

&a[0][0]既能夠看作數組0行0列的首地址,還能夠看作是二維數組的首地址;

&a[0]是第0行的首地址;

a[0]+n是第0行第n個元素的地址;

*(*(a+n)+m)表示第n行第m列元素;

*(a[n]+m)表示第n行第m列元素。

數組指針和指針數組

這個尚未理解好,尤爲是數組指針,指針數組還好理解,就是存儲指針變量的數組。

指針和字符數組

字符數組就是一個字符串,經過字符指針能夠指向一個字符串,而後經過地址的加減實現讀取。

傳遞地址

以前接觸的函數都是實參傳遞進函數體後,生成的是實參的副本,函數體內改變副本的值並不會影響到實參,可是若是傳遞進去的是指針,即便是副本指針,指向的地址仍是同樣的,所以能夠改變指針指向地址的內容。

指向函數的指針

指針變量也能夠指向一個函數。一個函數在編譯時被分配給了一個入口地址,這個地址能夠理解爲存放在函數名中,能夠定義函數指針,指向這個函數,經過指針來調用函數。

好比:

int sum(int x, int y)

int *a(int, int);

a = sum;

調用的時候這樣:

int c,d;

(*a)(c,d);

還能夠定義指針函數,返回值是指針,也就是地址了。

空指針調用函數

空類型指針指向任意類型函數或者將任意類型的函數指針賦值給空類型指針都是合法的。使用空指針調用自身所指向的函數仍然按照強制轉換的形式使用。

指針數組

 

構造數據類型

結構體

C++ struct結構體變量其實跟數組有點像,只不過數組是相同類型元素的集合,而結構體變量能夠是不一樣類型數據的集合。

定義結構體變量有兩種方式:一、在定義結構體的時候定義;二、定義完以後定義。

struct PersonInfo
{
    int index;
    char name[30];
    short age;
}XiaoMing;

或者
struct PersonInfo
{
    int index;
    char name[30];
    short age;
}
PersonInfo XiaoMing;

引用方式:1.使用成員運算符.來引用;2.定義結構體指針變量以後,使用指向運算符->來引用

 

結構體還能夠進行嵌套,結構體的大小通常狀況下都是結構體內成員的大小之和。

使用typedef能夠給一個複雜的數據類型定義一個別名,好比int(*)(int i)很複雜,就能夠用一個別名來代替。

 

枚舉類型enum的應用

枚舉類型就是用大括號將不一樣標識符放到一塊兒,變量的值只能取自括號內的值,在定義時,編譯器默認將標識符自動賦上整形常數。還能夠自行修改整形常數的值,說白了就是一個標識符對應一個常數,用於一些判斷或者什麼,用起來方便一些。賦值的時候,不能直接賦整型數,可是能夠經過強制類型轉換來賦值。枚舉類型的變量,實質實際上是整型的數字,因此能夠進行比較和運算。

結構體

結構體變量還能夠作函數的參數,還可使用結構體指針,使用結構體指針減小了時間和空間上的開銷,可以提升程序的運行效率。

結構體還能夠建立結構體數組,跟建立結構體變量同樣,在定義結構體時建立或者定義完了以後用結構體名這種數據類型建立。能夠定義結構體指針,指向數組,使用指向符號->進行讀取,可是要注意,指針加1,指向的就是數組裏的下一個結構體了。

共用體

共用體union數據類型其實和結構體很像,聲明共用體數據類型變量和聲明共用體變量同樣,都有三種方式,前兩種應該知道,第三種是省略了共用體數據類型變量名,在定義共用體以後接着聲明變量。

要注意共用體跟結構體最大的區別在於內存方面。共用體變量所佔的內存長度等於最長的成員的長度,一個共用體變量不能同時存放多個成員的值,某一時刻只能存放其實一個成員的值,這就是最後賦予他的值。

共用體的特色是:1.使用共用體變量的目的是但願用同一個內存段存放幾種不一樣類型的數據,可是某個瞬間只能存放一種,而不是同時存放幾種;2.可以被訪問的是最後一個被賦值的變量,對新的賦值後原來的就失去做用了;3.共用體變量的地址和它的各成員的地址都是同一地址。4.不能對共用體變量名賦值,不能引用變量名來獲得哦一個值,不能在定義共用體變量時對它初始化,不能做爲函數參數。

自定義數據類型

跟前面的數據類型重命名同樣的,使用typedef標識符進行類型的重命名,或者說是自定義數據類型,實際上是爲了寫起來方便或者用特定的單詞表明特殊的意思。

宏定義

使用#define 能夠對程序中常常出現的參數進行宏定義,這樣在以後寫代碼的時候就能夠用宏定義替換,必定程度上減輕了寫代碼的複雜度,程序在編譯的時候自動進行替換,好比PI,通常標識符習慣用大寫字母表示,以和變量名進行區分,要注意宏定義不是C語言,不須要在後面加分號,還能夠定義數組和運算,定義運算的時候,括號建議都加上,以防止出現錯誤。若是字符串長於一行,能夠在該行末尾用反斜槓\來續行。通常來說,定義只有,做用域即有效範圍指的是定義命令以後到此源文件結束,但也可經過#undef命令終止宏定義的做用域。

相關文章
相關標籤/搜索