指針
- 1.裸指針的基本概念
- 1.1 裸指針的聲明*/初始化&
- 1.2 操作裸指針--間接運算符*
- 1.3 裸指針使用 demo--指向一個簡單變量
- 1.4 空指針--nullptr
- 1.5 特殊指針--void *ptr
- 2.指針和引用--引用定義&
- 3.指針和數組
- 3.1 數組指針的定義
- 3.2 數組指針遞增/遞減操作
- 3.3 指針與數組使用的一些注意點
《老九學堂C++課程》《C++ primer》學習筆記。《老九學堂C++課程》詳情請到B站搜索《老九零基礎學編程C++入門》
-------------簡單的事情重復做,重復的事情用心做,用心的事情堅持做(老九君)---------------
1.裸指針的基本概念
指針是一個值為內存地址的變量(數據對象)。也就是說指針它一樣是一個變量,只不過該變量中存放的是另一個對象的內存地址,存放另一個對象的地址的操作又叫指向了該對象。
裸指針相對于智能指針而言,智能指針的使用詳見part 5
-
變量名–地址的助記符, 指針–存放內存地址
-
定義指針時不賦初值,該指針叫野指針。強烈建議初始化所有指針/盡量等定義了變量之后再定義指向它的指針.
-
指針指向的對象可以改變(可以通過賦值–去地址符號改變指針的內容)
-
指針類型與指向對象的類型匹配
-
裸指針需要手動釋放,否則會造成內存泄漏
1.1 裸指針的聲明*/初始化&
裸指針聲明 --僅聲明不初始化的指針是非常不安全的,所以推薦聲明完就初始化。
數據類型 * 指針變量名 // 定義一個指向(數據類型)變量的指針
int *ptr_num;
int *ptr_name;
int *money_ptr;
double *p_price;
注意:星號靠前靠后都是定義指針型變量,建議靠后結合知名該變量是指針。
int* a,b,c; //只有a為指向int 類型變量的指針,b、c是一般的int 型變量
int *a, *b, *c; //定義了3個指向int 類型變量的指針
裸指針初始化–取地址符號&,取變量的地址賦值給指針變量
int year;
year = 2021; // year 對應的變量塊中存放數2021
int *ptr_year; // 聲明一個指針變量
ptr_year = &year; // 將變量year的地址出來賦給指針變量,我們說的是ptr_year指向了year這個變量
1.2 操作裸指針–間接運算符*
操作裸指針–間接運算符*
間接運算符*作用于指針變量,取變量中的地址,然后對該地址對應的內存空間進行操作
int num = 1024;
int *ptr_num;
ptr_num = \#
*ptr_111; //等價于 num = 111;
注意:指針聲明之星號 和 間接運算符之星號 的作用完全不同
1.3 裸指針使用 demo–指向一個簡單變量
int main(){double num = 1024.5;double *ptr_num = #cout << "ptr_num 的值: " << ptr_num << "\t" << &num << endl;cout << "ptr_num指向空間的值: " << *ptr_num << endl;return 0;
}
輸出:
ptr_num 的值: 0x7ffee273f630 0x7ffee273f630
ptr_num指向空間的值: 1024.5
demo2:字符指針在輸出時候的注意事項
int mian(){char ch = 'a';char *ptr_ch = &ch;// 默認以字符串的方式打印字符(char 型指針被默認為帶有間隔操作符號) cout << ptr_ch << "\t" << *ptr_ch << endl;// 強制轉換成字符型指針(輸出地址,void * 任意的地址類型)cout << (void * )ptr_ch << "\t" << *ptr_ch << endl;return 0;
}
1.4 空指針–nullptr
空指針: 不指向任何對象指針。
作用: 初始化指針,避免出現野指針。
提示: 在使用一個指針前可以檢查它是否為空。
int *ptr1 = nullptr; // c++ nullptr 字面值常量 =0, 可以被轉換成任何類型的指針
int *ptr2 = 0;# include <cstdlib> // c 語法空指針
int *ptr3 = NULL
1.5 特殊指針–void *ptr
一種特殊的指針類型,可以存放各種類型變量的地址
注意1:void *指針不能用來訪問地址所指向的對象(即用* 取地址對應的內容)
void 使用技巧: 和別的指針比較、作為函數的輸入輸出、賦值給另一個void 指針
void 指針使用示例
int main(){// void 指針double objNum = 3.14;double *ptr_obj = &objNum;void *vptr_obj = &objNum;cout << (vptr_obj == ptr_obj) << endl;return 0;
}
2.指針和引用–引用定義&
引用:對象的一個別名,引用訪問變量時直接用引用名就可以了,不需要和指針一樣用*。
引用的定義
int int_val = 1024;
int& refValue = int_val; # 定義了變量int_val的引用refValue
引用的使用 :和所有的一般變量一樣使用即可
int num = 108;
int& rel_num = num;
rel_num = 118; // 直接使用引用對變量賦值
cout << &num << '\t' << &rel_num << endl;
// 輸出 操作的是同一塊內存空間,在使用數組或者對象的引用時,才會凸顯其優勢
0x7ffee750f60c 0x7ffee750f60c
常量引用: 一般情況下常量的引用是錯的,但是如果一定要定義一個常量的引用給可以使用const
double ref = 100.0;//?
const double ref = 100.0;//??
引用和指針的關系
- 引用是對指針的簡單封裝,底層仍然是指針。
- 引用在獲取地址時,編譯器內部會進行* 操作。
- C++提倡使用引用,而少用指針
- 引用的優勢-效率更高。指針賦值時的取地址符號&會驗證地址的有限性(編譯器內部機制?)而引用不需要,所以引用使用起來效率更高。
注意事項:
- 引用只能綁定在對象上,不能與字面值或者某個表達式的計算結果綁定在一塊。
- 引用都必須初始化,所以引用使用之前不需要測試其有效性。
3.指針和數組
數組數據是一塊連續的內存地址,數組名就是這塊連續內存空間的首地址
3.1 數組指針的定義
int main(){double score[] = {11, 22, 33, 44, 55};double *ptr_score = score; // 指向數組的指針,不需要取地址符號cout << sizeof(score) << '\t' << sizeof(ptr_score) << endl;cout << ptr_score[2] << endl; // 數組指針可以像數組名一樣使用下標操作數組return 0;
}
// 輸出
40 8 # 數組名對應的數據類型為double[5] 用sizeof 輸出時是40位
33
3.2 數組指針遞增/遞減操作
指針的++,–被視為指針的移動操作,移動下一個/上一個基本單位
int main(){double score[5] = {98, 87, 65, 43, 76};double *ptr_score = score;for(int i = 0; i < 5; i++){cout << *ptr_score++ << endl; // }return 0;
}
3.3 指針與數組使用的一些注意點
int num[50]; //num數組名,也可以理解成數組的首地址
// num的值和&num[0] 的值一致
// 數組第i+1個元素地址可以表示為:&num[i+1] num + i + 1
// 數組第i+1個元素可以表示為: num[i+1] 或者 *(num+i+1)
// 為指向數組的指針賦值
int *ptr_num = num;
int *ptr_num = &num[0];
//指針變量也可以指向數組元素
int *ptr_num = &num[4]
int *ptr_num = num + 4