C++Primer第四版第四章要點總結!

第四章 數組和指針

4.1 數組

  • 數組的長度是固定的,而無法直接知道一個給定數組的長度。數組一經創建,就不允許添加新的元素
  • 沒有所有元素都是引用的數組,即數組元素不能是引用。
  • 在函數體外定義的內置數組,其元素均初始化爲 0
  • 在函數體內定義的內置數組,其元素無初始化
  • 不管數組在哪裏定義,如果其元素爲類類型則自動調用該類的默認構造函數進行初始化;如果該類沒有默認構造函數,則必須爲該數組的元素提供顯式初始化。
  • 不能用一個數組初始化另一個數組。
int a[2] = {1,2};
int b[2];
b = a; //非法操作
  • 數組支持隨機訪問,默認下標從0開始。

4.2 指針

  • & 取地址操作符只能用於左值。
  • 指針只能指向同類型的對象。
  • 如果需要在一個聲明語句中定義兩個指針,必須在每個變量標識符前再加符號 * 聲明
int a = 3;
int *p1, *p2;               //定義了兩個int類型的指針
int *p3, p4;                //定義了一個int型的指針p3和一個int變量p4
p1 = &a;                    //p1指針指向a變量
std::cout << *p1 <<endl;    //輸出p所指向變量的值
  • void 類型的指針可以指向任意類型的變量*,該類型指針不能操縱他所指向的對象。僅支持以下操作:
    1.與另一個指針進行比較.
    2.作爲參數或者函數的返回值.
    3.給另一個 void* 指針賦值
  • 指針和引用的區別:
    1.引用在定義時必須初始化,且它不能修改
    2.給引用賦值是修改該引用關聯對象的值,給指針賦值是使指針指向新的對象,原指向對象的值不改變。
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
p1 = p2;                //現在p1指向了b變量
int &r1 = a, &r2 = b;
r1 = r2;                //此時b的值被賦給a
  • 在指針上加上(或減去)一個整型數值 n 等效於獲得一個新指針,
    該新指針指向指針原來指向的元素之後(或之前)的第 n 個元素。
  • 允許在指針上加減0,使指針保持不變。更有趣的是,如果一指針具有 0 值(空指針),則在該指針上加 0 仍然是合法的,結果得到另一個值爲 0 的指針。
    也可以對兩個空指針做減法操作,得到的結果仍是 0。 - 用指針遍歷數組
const int N = 5;
int a[N] = {0, 1, 2, 3, 4};
//p1指向數組第一個元素,p2指向最後一個元素之後的那個位置。
for(int *p1 = a, *p2 = a + N; p1 != p2; ++p1)
    cout << *p1 <<" "; 
  • 指向const對象的指針:const限定的是指針cp所指向的對象類型,而不是指針本身,可以修改使其指向另一個const對象,但不允許修改其所指對象的值。
  • 不能使用“void*”指針保存const對象的地址,必須使用“const void*” 指針。
const int a = 1;
int b = 2;
const int c = 3;
const int *cp;      //這裏指針cp指向一個int類型的const對象,也就是說該指針只能指向const的對象
cp = &a;            //合法
cp = &b;            //非法,該指針只能指向const對象
cp = &c;            //合法
int *p2;
p2 = &a;            //非法,不能將一個const對象的地址賦給一個非const對象的指針。
  • const指針:該指針不可修改,但是該指針指向對象的值是可以修改的const指針也必須在定義時初始化。任何試圖給const指針賦值的行爲都不合法(及時用它自己給自己賦值)。
int a = 1, b = 2;
int *const p = &a;
*p = 3;             //合法
p = &b;             //非法
  • 指向const對象的const指針:既不能修改該指針,又不能修改該指針所指向的對象的值
typedef string *pstring;
const pstring cstr;
  • 上例不能理解爲 const string *cstr;而應該理解爲 string *const cstr;

4.3 C風格字符串

  • C++ 語言通過(const)char*類型的指針來操縱 C 風格字符串。
  • 常用C風格字符串操作函數(需包含頭文件 #include ):
函數 描述
strlen(s) 返回s的長度,不包括字符串結束符。
strcmp(s1, s2) 若s1==s2,返回0;s1>s2,返回正數;否則返回負數。
stract(s1, s2) 將s2連接到s1末尾,返回s1
strcpy(s1, s2) 將s2賦值給s1
strncat(s1, s2, n) 將s2前n個字符連接到s1後面,返回s1
strncpy(s1, s2, n) 將 s2 的前 n 個字符複製給 s1,並返回 s1
  • strlen總是假定其參數字符串以null字符結束,若不是則會出錯。
char ca[] = {'C', '+', '+'};    //沒有null結束符
cout << strlen(ca) << endl;     //出錯,不能這樣使用
  • 每一個程序在執行時都佔用一塊可用的內存空間,用於存放動態分配的對象,此內存空間稱爲程序的自由存儲區或堆。在自由存儲區中創建的數組對象是沒有名字的,只能通過地址訪問。
int *pia = new int[10];     //分配了一個含有10元素的數組,並將數組首指針返回給pia
  • 動態分配數組時,如果數組元素具有類類型,將使用該類的默認構造函數實現初始化;如果數組元素是內置類型,則無初始化。也可使用跟在數組長度後面的一對空圓括號,對數組元素做值初始化。對於動態分配的數組,其元素只能初始化爲元素類型的默認值,而不能像數組變量一樣,用初始化列表爲數組元素提供各不相同的初值。如果我們在自由存儲區中創建的數組存儲了內置類型的const對象,則必須爲這個數組提供初始化
int *pia2 = new int[10] ();     //初始化爲0
// 錯誤,未初始化const對象
const int *pci_bad = new const int[100];
// 正確
const int *pci_ok = new const int[100]();
  • C++ 允許定義類類型的const數組,但該類類型必須提供默認構造函數。
  • C++ 雖然不允許定義長度爲0的數組變量,但調用 new 動態創建長度爲0的數組是合法的。new動態創建長度爲0的數組時,new返回有效的非零指針。該指針與new 返回的其他指針不同,不能進行解引用操作,因爲它畢竟沒有指向任何元素,可以進行比較,加0,減去自身得到0。
  • C++ 語言爲指針提供delete[]表達式釋放指針所指向的數組空間,如果遺漏方框會產生內存泄漏,發生嚴重錯誤。
int *p = new int[n]();
delete [] p;
  • string 類型的加法操作需要兩個操作數,可以使用 C 風格字符串作爲其中的一個操作數,也允許將C風格字符串用作複合賦值操作的右操作數。反之:在要求C 風格字符串的地方不可直接使用標準庫 string 類型對象。如無法使用string對象初始化字符指針
string s2("he");
char *str = st2;            //錯誤
char *str = st2.c_str();    //使用c_str()函數可以完成賦值,該函數返回指向字符數組首地址的指針
  • 可以用數組初始化vector
const size_t arr_size = 6;
int int_arr[arr_size] = {0, 1, 2, 3, 4, 5};
// ivec has 6 elements: each a copy of the corresponding element in int_arr
vector<int> ivec(int_arr, int_arr + arr_size);
vector<int> ivec(int_arr + 1, int_arr + 4);

4.4多維數組

int ia[3][4] = {
    {0,1,2, 3},
    {4,5,6,7},
    {4,5,6,7}
};       //聲明並且初始化一個三行四列的二維數組

int ib[3][4] = {0, 3, 6, 9};        //該聲明初始化了第一行的元素,其餘元素都被初始化爲 0。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章