c++指針和引用的詳細介紹
1筑舅、指針和引用的區(qū)別
指針-對于一個類型T,T就是指向T的指針類型陨舱,也即一個T類型的變量能夠保存一個T對象的地址翠拣,而類型T是可以加一些限定詞的,如const游盲、volatile等等误墓。
引用-引用是一個對象的別名,主要用于函數(shù)參數(shù)和返回值類型益缎,符號X&表示X類型的引用谜慌。
(1)引用不可以為空,但指針可以為空链峭。前面也說過了引用是對象的別名畦娄,引用為空——對象都不存在,怎么可能有別名!故定義一個引用的時候熙卡,必須初始化杖刷。
(2)引用不可以改變指向,對一個對象"至死不渝"驳癌;但是指針可以改變指向滑燃,而指向其它對象。說明:雖然引用不可以改變指向颓鲜,但是可以改變初始化對象的內(nèi)容表窘。例如就++操作而言,對引用的操作直接反應到所指向的對象甜滨,而不是改變指向乐严;而對指針的操作,會使指針指向下一個對象衣摩,而不是改變所指對象的內(nèi)容昂验。見下面的代碼:
#include<iostream>
using namespace std;
int main(int argc,char** argv)
{
int i=10;
int& ref=i;
ref++;
cout<<"i="<<i<<endl;
cout<<"ref="<<ref<<endl;
int j=20;
ref=j;
ref++;
cout<<"i="<<i<<endl;
cout<<"ref="<<ref<<endl;
cout<<"j="<<j<<endl;
return 0;
}
對ref的++操作是直接反應到所指變量之上,對引用變量ref重新賦值"ref=j"艾扮,并不會改變ref的指向既琴,它仍然指向的是i,而不是j泡嘴。理所當然甫恩,這時對ref進行++操作不會影響到j。而這些換做是指針的話酌予,情況大不相同磺箕,請自行實驗。輸出結果如下:
- 引用的大小是所指向的變量的大小霎终,因為引用只是一個別名而已滞磺;指針是指針本身的大小,4個字節(jié)莱褒。
int main()
{
string str = "123456";
string &str_ref = str;
string *str_ptr = &str;
cout<<"str.size = "<<sizeof(str)<<endl;
cout<<"str_ref.size = "<<sizeof(str_ref)<<endl;
cout<<"str_ptr = "<<sizeof(str_ptr)<<endl;
}
結果:
str.size = 24
str_ref.size = 24
str_ptr = 8
- 引用比指針更安全。由于不存在空引用涎劈,并且引用一旦被初始化為指向一個對象广凸,它就不能被改變?yōu)榱硪粋€對象的引用,因此引用很安全蛛枚。對于指針來說谅海,它可以隨時指向別的對象,并且可以不被初始化蹦浦,或為NULL扭吁,所以不安全。const 指針雖然不能改變指向,但仍然存在空指針侥袜,并且有可能產(chǎn)生野指針(即多個指針指向一塊內(nèi)存蝌诡,free掉一個指針之后,別的指針就成了野指針)枫吧。
指針指向一塊內(nèi)存浦旱,它的內(nèi)容是所指內(nèi)存的地址;而引用則是某塊內(nèi)存的別名九杂,引用不改變指向颁湖。
2、常量指針例隆、常量引用甥捺、指針常量
2.1常量指針
常量指針:指向常量的指針,在指針定義語句的類型前加const镀层,表示指向的對象是常量镰禾。
int i = 10;
const int* p = &i;
*p = 20; // 錯誤的
i = 20;
cout << i << endl; // 20
cout << (*p) << endl; // 20
常量指針定義"const int* pointer=&a"告訴編譯器,* pointer是常量鹿响,不能將 * pointer作為左值進行操作羡微。但是可以通過修改i的數(shù)值達到修改*p的數(shù)值。
2.2常量引用
常量引用:指向常量的引用惶我,在引用定義語句的類型前加const妈倔,表示指向的對象是常量。也跟指針一樣不能利用引用對指向的變量進行重新賦值操作绸贡。
int i = 10;
const int& ref = i;
ref = 20; // 錯誤的
i = 20;
cout << ref << endl; // 20
可以將ref理解為一個常量盯蝴,無法直接修改,但是可以通過修改i的數(shù)值來修改ref的數(shù)值
2.3 指針常量
在指針定義語句的指針名前加const听怕,表示指針本身是常量捧挺。在定義指針常量時必須初始化!而這是引用天生具來的屬性尿瞭,不用再引用指針定義語句的引用名前加const闽烙。
int* const p; // 錯誤的,必須在聲明的同時被初始化
int b = 10;
int* const pointer=&b; // 正確
int c = 20;
pointer = &c; // 錯誤
*pointer = c;
c = 30;
cout << b << endl; // 20
cout << *pointer << endl; // 20
cout << c << endl; // 30
指針常量定義"int* const pointer=&b"告訴編譯器声搁,pointer是常量黑竞,不能作為左值進行操作,但是允許修改間接訪問值疏旨,即*pointer可以修改很魂。(pointer是一個固定的地址,不能修改檐涝,但是放在該地址上的數(shù)值可以一直被修改,pointer不能再重新指向別的數(shù)據(jù)了)
2.4 常量指針常量
int c =10;
const int *const pointer=&c;
c =20;
cout << *pointer << endl; // 20
常量指針常量:指向常量的指針常量遏匆,可以定義一個指向常量的指針常量法挨,它必須在定義時初始化。常量指針常量定義"const int* const pointer=&c"告訴編譯器幅聘,pointer和*pointer都是常量凡纳,他們都不能作為左值進行操作。
3.題目
const char * arr = "123"; // 不能修改喊暖, "123"是放在靜態(tài)存儲區(qū)
char * brr = "123"; // 不能修改 "123"放在靜態(tài)存儲區(qū)
const char crr[] = "123"; // 不能修改 (可能放在棧也可能放在靜態(tài)存儲區(qū)惫企,看具體編譯器)
char drr[] = "123"; // 可以修改,放在棧上