一、基本知識
指標和引用的宣告方式:
宣告指標: char* pc;
宣告引用: char c = 'a'
char& rc = c;
它們的區別:
①從現象上看,指標在執行時可以改變其所指向的值,而引用一旦和某個物件繫結後就不再改變。這句話可以理解為:指標可以被重新賦值以指向另乙個不同的物件。但是引用則總是指向在初始化時被指定的物件,以後不能改變,但是指定的物件其內容可以改變。
②從記憶體分配上看,程式為指標變數分配記憶體區域,而不為引用分配記憶體區域,因為引用宣告時必須初始化,從而指向乙個已經存在的物件。引用不能指向空值。
③從編譯上看,程式在編譯時分別將指標和引用新增到符號表上,符號表上記錄的是變數名及變數所對應位址。指標變數在符號表上對應的位址值為指標變數的位址值,而引用在符號表上對應的位址值為引用物件的位址值。符號表生成後就不會再改,因此指標可以改變指向的物件(指標變數中的值可以改),而引用物件不能改。這是使用指標不安全而使用引用安全的主要原因。從某種意義上來說引用可以被認為是不能改變的指標。
④不存在指向空值的引用這個事實意味著使用引用的**效率比使用指標的要高。因為在使用引用之前不需要測試它的合法性。相反,指標則應該總是被測試,防止其為空。
⑤理論上,對於指標的級數沒有限制,但是引用只能是一級。如下:
int** p1; // 合法。指向指標的指標
int*& p2; // 合法。指向指標的引用
int&* p3; // 非法。指向引用的指標是非法的
int&& p4; // 非法。指向引用的引用是非法的
注意上述讀法是從左到右。
#include "stdio.h"
int main(void)
二、作為引數傳遞
利用引用的這個特性,可以用它作為函式的傳出引數。如程式3:
#include #include using namespace std;
int newevaluation(string& astr)
int main(void)
當然程式3引用傳遞的方式也可以寫成指標傳遞的方式,如程式5:
#include #include using namespace std;
int newevaluation(string* const astr)
int main(void)
三、函式指標和函式引用
函式指標是c++最大的優點之一。和使用普通指標相比,高階程式設計師只要有可能都更願意使用引用,因為引用更容易處理一些。然而,當處理函式時,函式引用對比函式指標就未必有這個優勢了。現有的**很少使用函式引用。下面將向介紹如何函式指標、如何使用函式引用以及分別在什麼情況下使用它們。
① 函式指標的例子
#include void print(int i)
void multiply(int& ndest, int nby)
void print_something()
int sayhello()
int main()
② 函式引用的例子
#include void print(int i)
void print2(int i)
void multiply(int& ndest, int nby)
void print_something()
int sayhello()
int main()
總結:
函式指標的宣告使用方式:
《想要指向的函式之返回型別》(*函式指標的名稱)《想要指向的函式之引數型別…>
如要想宣告乙個函式指標指向以下函式:
void print(int i)
那麼就可以如下操作:
void (*pfunction)(int);
然後如下用函式的位址給pfunction賦值:
pfunction = &print;
在然後,pfunction就可以和函式print一樣使用了,比如,
pfunction(1);
等等。函式引用的宣告和使用方式:
《欲引用的函式之返回型別》(&函式引用的名稱)《欲引用的函式之引數型別…>=《欲引用的函式的名稱》,至所以如此,是引用在宣告的時候必須初始化,引用不能指向空值。
如要想宣告乙個函式引用指向以下函式:
void print(int i)
那麼就可以如下操作:
void (&rfunction)(int)=print;
在然後,rfunction就可以和函式print一樣使用了,比如,
rfunction(1);
等等。四、const修飾指標和引用
大致而言,const修飾指標和引用分三種情況,即const修飾指標、const修飾引用和const修飾指標的引用。下面分別討論之。
① const修飾指標
const修飾指標又分為三種情況,即const修飾指標本身、const修飾指標所指的變數(或物件)以及const修飾指標本身和指標所指的變數(或物件)。
a. const修飾指標本身
在這種情況下,指標本身是常量,不能改變,任何修改指標本身的行為都是非法的,例如:
double pi = 3.1416;
double* const pi = π
double alpha = 3.14;
pi = α // 錯誤。因為指標pi是常量,不能再被改變。
*pi = alpha; // ok。雖然指標pi不能被改變,但指標所指的變數或者物件可變。
b. const修飾指標指向的變數(或物件)
在這種情況下,指標本身可以改變,但const所修飾的指標所指向的物件不能被改變,例如:
double pi = 3.1416;
const double* pi = π
double alpha = 3.14;
*pi = alpha; // 錯誤。因為pi所指向的內容是常量,因此*pi不能被改變。
pi = α // ok。雖然指標所指的內容不能被改變,但指標pi本身可改變。從而通過這種方式改變*pi。
c. const修飾指標本身和指標所指向的變數(或物件)
在這種情況下,指標本身和指標指向的變數(或物件)均不能被改變,例如:
double pi = 3.146;
const double* const pi = π
//double const* const pi = π
cout << "pi = " << pi << endl;
cout << "*pi = " << *pi << endl;
double alpha = 3.14;
//*pi = alpha; // 錯誤。因為pi所指向的內容是常量,因此*pi不能被改變。
//pi = α // 錯誤。因為指標pi是常量,不能再被改變。
② const修飾引用
const修飾引用沒有指標修飾指標那麼複雜,只有一種形式。引用本身不能被改變,但所指向的物件是可以被改變的,見上面「一、基本知識」。
double pi = 3.1416;
//const double& pi = pi;
double const& pi = pi; //和上面一句是等價的
//double& const pi = pi; //有問題。很多編譯器會產生warning
cout << pi << endl;
③ const修飾指標引用
我們用例子來說明。
double pi = 3.14;
const double* ppi = π
//const double*& rpi = π //錯誤。不能將double* 轉換成const double *&
const double*& rpi = ppi; //ok。宣告指標引用的正確方法
說明:const double*& rpi = π 為什麼會出現錯誤呢?我們知道,引用是被引用物件的別名,正因為如此,由於rpi是ppi的別名,因此rpi和ppi的型別必須完全一致。從上面的**段我們可以看到,rpi的型別是const double*,而&pi的型別是double*,因此這句程式是錯誤的。
下面這段**和 ① 中的b中的情形對應(即內容不可變,指標可變):
double pi = 3.1416;
double api = 3.14;
const double* ppi = π
const double* papi = &api;
const double*& rpi = ppi;
const double*& rapi = ppi;
*rapi = api; // 錯誤。指標所指向的值不能被直接改變
rapi = papi; // ok。指標本身可以被改變
指標引用的用法還有其它的情形,由於罕用,故此不談及。
本文**:
C 常量指標 指標常量 引用和常引用的用法解析
今天學習c 的常量型別和引用,其中常量指標 指標常量 引用和常引用幾個概念較為接近,特地整理一下。1.常量指標 pointer to const 常量指標,顧名思義,是指向常量的指標,其定義的一般形式為 const t pointer name t為資料型別,target為t類資料。常量指標本身是可...
指標引用的用法
指標引用就是乙個指標的引用,看下面例1 int a 10 int b 20 void swap int lhs,int rhs swap a,b 上面的程式可以成功交換兩個int值,但是如果形參傳的是int而非其引用的話則不會交換2個int值,因為形參非引用的情況下,編譯器會複製a,b然後把a,b的...
指標引用的用法
指標引用就是乙個指標的引用,看下面例1 int a 10 int b 20 void swap int lhs,int rhs swap a,b 上面的程式可以成功交換兩個int值,但是如果形參傳的是int而非其引用的話則不會交換2個int值,因為形參非引用的情況下,編譯器會複製a,b然後把a,b的...