注意以下細節
(1)###
int *ptr;
強調 *ptr 是一個int類型的值
int* ptr;
強調 int* 一種類型,是指向int的指針
(2)###
下面的代碼中
int* p1, p2;
聲明了一個指針 p1 和一個常規變量 p2,也就是說,對于每一個指針變量名,都需要使用一個 (*) 號:
int *p1, *p2;
(3)###
int *i_ptr;
double *f_ptr;
char *ch_ptr;
盡管他們都是指針,卻是不同類型的指針(指針基于其它類型);
*i_ptr *f_ptr *ch_ptr 指向長度不同的數據類型,但它們本身的長度通常是相同的,即地址的長度。
(4)###
int higgens = 5;
int *pt = &higgens;
將pt(而不是*pt)的值設置為&higgens,即:
int higgens= 5;
int *pt;
pt = &higgens;
(5)###
警告:一定要在對指針使用解除引用操作符(*)之前,將指針初始化為一個確定的、適當的地址。
(6)###
給指針賦地址(數字整型)的一種方法,是強制類型轉換:
int *pt;
pt = (int*)0x8000000;
(7)###
使用 new 和 delete 時,應遵守以下規則:
- 不要使用 delete 刪除不是 new 分配的內存;
- 不要使用 delete 釋放同一內存兩次;
- 如果使用 new[] 為數組分配內存,則應使用 delete[] 來釋放;
- 如果使用 new[] 為一個實體分配內存,則應使用 delete 來釋放;
- 對空值指針使用 delete 是安全的。
(8)###
可以用指針代替數組名是因為:你可以修改指針的值,而數組名是常量:
pointername = pointername + 1; // right
arrayname = arrayname + 1; // error 是常量,不能進行賦值
(9)###
對數組名應用sizeof得到的是數組的長度,而對指針應用sizeof得到的是指針的長度(與平臺相關,通常為4)。
(10)###
cout.setf(ios_base::boolalpha);
使其后的表達式的cout語句的結果以“bool”方式顯示
(11)###
遞增/遞減操作符和指針(假設pt指向a[1])
*++pt; // 此時pt指向a[2]
++*pt; // “a[2]+1”
(*pt)++; // “a[2]++”
*pt++; // pt仍指向a[2],但是該語句完成后,pt的值為a[3]的地址
(12)###
可以使用如下方式讀取標準輸入
for (cin>>x; x==0 ; cin>>x); // 如果 x == 0 繼續輸入
(13)###
如果不對函數內部定義的變量進行初始化,該變量的值將是不確定的。這意味著該變量的值將是它被創建之前,該內存單元保存的值。
(14)###
C++ 通常的約定是,退出值為 0 則意味著程序運行成功,為非零則意味著存在問題。
(15)###
C++ 中,在可以使用數字轉義序列或符號轉義序列(如 \0x8 和 \b)時,應使用符號序列。數字表示與特定的編碼方式(如 ASCII 碼)相關,而符號表示適用于任何編碼方式,其可讀性也更強。
(16)###
如果你在學習 C++ 之前學習了 C 語言,并打算使用 #define 來定義符號常量,請不要這樣做,而應使用 const。
(17)###
C++ 不提倡使用外部變量,但是提倡外部結構( struct )聲明。另外,在外部聲明符號常量通常更合理。
(18)###
警告:一定要在對指針應用解除引用操作符(*)之前,將指針初始化為一個確定的、適當的地址。這是關于指針的金科玉律。
(19)###
在 cout 和多數 C++ 表達式中,char 數組名、指向 char 的指針以及用引號括起的字符串常量都被解釋為字符串第一個字符的地址。
(20)###
必須在聲明引用時進行初始化(int & zdsTest = tiger;)。
(21)###
返回引用的函數實際上是被引用變量的別名。
(22)###
應避免返回當函數終止時不再存在的內存單元引用。
(23)###
結構的默認訪問類型是 public,而類為 private。C++ 通常把結構限制為只表示純粹的數據對象或沒有私有部分的類。
(24)###
缺省形參值的說明次序:必須以從右向左的順序來聲明,并且缺省形參的右面不能有非缺省形參值的參數。因為調用時實參取代形參是從左向右的順序。
(25)###
如果既可以通過初始化,也可以通過賦值來設置對象的值,則應采用初始化的方式。通常這種方式效率更高。舉例:
Exam e1 = Exam("zds",25,12); // #1
Exam e2;
e2 = Exam("Toby",25,12); // #2
#1語句是初始化,它創建有指定值的對象,可能會創建臨時對象(也可能不會);#2語句是賦值。像這樣在賦值語句中使用構造函數總會導致在賦值前創建一個臨時對象。
(26)###
在默認情況下,將一個對象賦給同類型的另一個對象時,C++ 將源對象的每個數據成員的內容復制到目標對象中相應的數據成員中。
(27)###
記住:接受一個參數的構造函數允許使用賦值句法來將對象初始化為一個值。例:
Exam zdsEx = value;
(28)###
要創建類對象數組,則這個類必須有默認構造函數。
(29)###
不要返回指向局部變量或臨時對象的引用。函數執行完畢后,局部變量和臨時對象將消失,引用將指向不存在的數據。
(30)###
在類聲明中定義的函數,將自動成為內聯函數。
(31)###
如果方法通過計算得到一個新的類對象,則應考慮是否可以使用類構造函數來完成這種工作。這樣不僅可以避免麻煩,而且可以確保新的對象是按照正確的方式創建的。例如:
Exa Exa::zdsText(const Exa& bExa) const{
Exa zdsExa;
zdsExa.x = x + bExa.x;
zdsExa.y = y + bExa.y;
return zdsExa;
}
可以用如下“更好”的代碼取代:
Exa Exa::zdsText(const Exa& bExa) const{
return Exa(x + bExa.x,y + bExa.y);
}
當然,我們的類中需要有對應 Exa(x + bExa.x, y + bExa.y) 的構造函數。
(32)###
只接受一個參數的構造函數定義了從參數到類類型的轉換。但是如果使用關鍵字 explicit 限定了這種構造函數,則它就只能用于顯示轉換,否則也可以用于隱式轉換。
(33)###
使用 delete 刪除對象可以釋放對象本身占用的內存,但并不能自動釋放屬于對象成員的指針指向的內存。因此,必須使用析構函數。在析構函數中使用 delete 語句可確保對象過期時,由構造函數使用 new 分配的內存被釋放。
(34)###
指針策略是 C++ 內存管理理念的核心,它將地址視為指定的量,而將值視為派生量。一種特殊類型的變量——指針——用于存儲值的地址。因此,指針名表示的是地址。* 操作符稱為間接值或解除引用操作符,將其應用于指針,可以得到該地址處存儲的值(這和乘法使用的符號相同;C++ 根據上下文來確定所指的是乘法還是解除引用)。
(35)###
* 操作符兩邊的空格是可選的。傳統上,C 程序員使用這種格式:
int *ptr;
這里強調 *ptr 是一個 int 類型的值。而很多 C++ 程序員使用這種格式:
int* ptr;
這里強調的是 int* 是一種類型,是指向 int 的指針。在哪里添加空格對于編譯器來說是沒有任何區別的。不過:
int* ptr1,ptr2;
將創建一個指針(ptr1)和一個常規 int 變量(ptr2)。對于每個指針變量名,都需要使用一個 *
(36)###
雖然指針指向的數據類型的長度可能不同,但指針變量本身的長度通常是相同的。
(37)###
指針的危險
極其重要的一點是:在 C++ 中創建指針時,計算機將分配用來存儲地址的內存,但不會分配用來存儲指針所指向的數據的內存。為數據提供空間是一個獨立的步驟,忽略這一步驟無疑是自找麻煩。
警告:一定要在對指針應用解除引用操作符(*)之前,將指針初始化為一個確定的、適當的地址。這是關于指針的金科玉律。
(38)###
要將數字值作為地址來使用,應通過強制類型轉換將數字轉換為適當的地址類型:
int* ptr;
ptr =(int*)0xB8000000;
(39)###
只能用 delete 來釋放由 new 分配的內存。這并不意味著要使用用于 new 的指針,而是用于 new 的地址。不過,對空指針使用 delete 是安全的。
(40)###
可以修改指針的值,因為它是變量。但是不能修改數組名的值,因為數組名是常量。
(41)###
對數組名使用 sizeof 操作符得到的是數組的長度,而對指針應用 sizeof 得到的是指針的長度,即使指針指向的是一個數組。
(42)###
絕對不要對為被初始化為適當地址的指針解除引用。
(43)###
在 cout 和多數 C++ 表達式中,char 數組名、指向 char 的指針以及用引號括起的字符串常量都被解釋為字符串第一個字符的地址。