C++的指針和引用

指針就是指向變量的地址,而引用是變量的別名,通過指針或引用都可以修改變量的值,但兩者的使用上會有一些差異,比如:

  1. 引用在定義的時候必須初始化,且只能指向一個變量,後續不能指向其它變量。而指針在定義的時候可以不初始化,且後續可以修改指向爲其它地址;
  2. 引用的大小是所指向變量的大小,而指針的大小則是固定的,32位系統爲4字節,64位系統位8字節;
  3. 引用比指針更安全,因爲引用在定義的時候必須初始化,所以不可能爲空,而指針可能爲空,所以指針使用前必須判空;
  4. 引用可以直接使用,而指針需要用*;

還是通過代碼來理解,定義了幾個函數:

void print(int *pn)
{
    cout<<"print(int *pn): pn\t"<<pn<<endl;
    cout<<"print(int *pn): &pn\t"<<&pn<<endl;
    cout<<"print(int *pn): *pn\t"<<*pn<<endl;
    *pn = 12;
}

void print(int &pn)
{
    cout<<"print(int &pn): pn\t"<<pn<<endl;
    cout<<"print(int &pn): &pn\t"<<&pn<<endl;
    pn = 13;
}

void print2(int *&pn)
{
    cout<<"print2(int *&pn): *pn\t"<<*pn<<endl;
    cout<<"print2(int *&pn): &pn\t"<<&pn<<endl;
    cout<<"print2(int *&pn): pn\t"<<pn<<endl;
    *pn = 14;
}
	int n = 10;
    int *pn = &n;
    cout<<"例子1: 傳指針 ---------->"<<endl;
    print(pn);

    cout<<__func__<<"\tpn\t"<<pn<<endl;
    cout<<__func__<<"\t&pn\t"<<&pn<<endl;
    cout<<__func__<<"\t*pn\t"<<*pn<<endl;

    cout<<"例子2: 傳引用 ---------->"<<endl;
    print(*pn);

    cout<<__func__<<"\tpn\t"<<pn<<endl;
    cout<<__func__<<"\t&pn\t"<<&pn<<endl;
    cout<<__func__<<"\t*pn\t"<<*pn<<endl;

    cout<<"例子3: 傳指針引用 ---------->"<<endl;
    print2(pn);

    cout<<__func__<<"\tpn\t"<<pn<<endl;
    cout<<__func__<<"\t&pn\t"<<&pn<<endl;
    cout<<__func__<<"\t*pn\t"<<*pn<<endl;

輸出結果:

例子1: 傳指針 ---------->
print(int *pn): pn	0x7ffeed4af9b4
print(int *pn): &pn	0x7ffeed4af828
print(int *pn): *pn	10
main	pn	0x7ffeed4af9b4
main	&pn	0x7ffeed4af9a8
main	*pn	12
例子2: 傳引用 ---------->
print(int &pn): pn	12
print(int &pn): &pn	0x7ffeed4af9b4
main	pn	0x7ffeed4af9b4
main	&pn	0x7ffeed4af9a8
main	*pn	13
例子3: 傳指針引用 ---------->
print2(int *&pn): *pn	13
print2(int *&pn): &pn	0x7ffeed4af9a8
print2(int *&pn): pn	0x7ffeed4af9b4
main	pn	0x7ffeed4af9b4
main	&pn	0x7ffeed4af9a8
main	*pn	14

在例子1中,print(int *pn)函數和main函數輸出的&pn是不一樣的,一個是0x7ffee9fa9838,一個是0x7ffee9fa99a8,因爲print(int *pn)函數是傳值,沒錯,傳值,只是這個值是“指針”,它會生成一個指針的副本,因此print(int *pn)函數和main函數輸出的&pn會不一樣。

注意⚠️,還有一個容易忽視的錯誤,看代碼:

void testPtr(int *pi)
{
    pi = new int;
    cout<<__func__<<"\t"<<pi<<endl;
}

int main() {
	int *pi = new int(100);
	cout<<"pi -> "<<pi<<endl;
	testPtr(pi);
	cout<<"pi -> "<<pi<<endl;
}

運行結果:

pi -> 0x7fa03b402ae0
testPtr	0x7fa03b402af0
pi -> 0x7fa03b402ae0

可能有人會認爲在testPtr能夠修改pi的值,但正如上面所說的,指針是傳值,作爲testPtr的參數時,是生成了一個指針的副本,因此在testPtr函數內,修改的是指針副本的值,而不是main函數中定義的pi的值。

還有一個關於引用的例子,看代碼:

int &max(int &a, int &b)
{
    return a > b ? a : b;
}

    int n1 = 11, n2 = 12;
    cout<<++max(n1,n2)<<"\t"<<n1<<"\t"<<n2<<endl;

程序輸出:

13	11	13

max函數返回的是n2的引用,因此++max(n1,n2)會修改n2的值⚠️。

參考
參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章