const T、const T*、T *const、const T&、const T*& 的區別,const

來源:互聯網
上載者:User

const T、const T*、T *const、const T&、const T*& 的區別,const

這裡的T指的是一種資料類型,可以是int、long、doule等基礎資料型別 (Elementary Data Type),也可以是自己類型的類型class。單獨的一個const你肯定知道指的是一個常量,但const與其他類型聯合起來的眾多變化,你是不是就糊塗了?下面我們一一來解析。

const T

定義一個常量,聲明的同時必須進行初始化。一旦聲明,這個值將不能被改變。

int i = 5;const int constInt = 10;        //正確const int constInt2 = i;        //正確constInt = 20;                  //錯誤,常量值不可被改變const int constInt3;            //錯誤,未被初始化
const T*

指向常量的指標,不能用於改變其所指向的對象的值。

const int i = 5;const int i2 = 10;const int* pInt = &i;           //正確,指向一個const int對象,即i的地址//*pInt = 10;                   //錯誤,不能改變其所指缶的對象pInt = &i2;                     //正確,可以改變pInt指標本身的值,此時pInt指向的是i2的地址const int* p2 = new int(8);     //正確,指向一個new出來的對象的地址delete p2;                      //正確//int* pInt = &i;               //錯誤,i是const int類型,類型不符,不能將const int * 初始化為int *int nValue = 15;const int * pConstInt = &nValue;    //正確,可以把int *賦給const int *,但是pConstInt不能改變其所指向對象的值,即nValue*pConstInt = 40;                    //錯誤,不能改變其所指向對象的值
const int* 與int* const的區別

指標本身就是一種對象,把指標定義為常量就是常量指標,也就是int* const的類型,也可以寫成int *const,聲明時必須初始化。

int nValue = 10;int* const p = &nValue;int *const p2 = &nValue;const int* 指標指向的對象不可以改變,但指標本身的值可以改變;int* const 指標本身的值不可改變,但其指向的對象可以改變。int nValue1 = 10;int nValue2 = 20;int* const constPoint = &nValue1;//constPoint = & nValue2;           //錯誤,不能改變constPoint本身的值*constPoint = 40;                   //正確,可以改變constPoint所指向的對象,此時nValue1 = 40const int nConstValue1 = 5;const int nConstValue2 = 15;const int* pPoint = &nConstValue1;//*pPoint  = 55;                    //錯誤,不能改變pPoint所指向對象的值pPoint = &nConstValue2;             //正確,可以改變pPoint指標本身的值,此時pPoint邦定的是nConstValue2對象,即pPoint為nConstValue2的地址

const int* const 是一個指向常量對象的常量指標,即不可以改變指標本身的值,也不可以改變指標指向的對象。

const int nConstValue1 = 5;const int nConstValue2 = 15;const int* const pPoint = &nConstValue1;//*pPoint  = 55;                    //錯誤,不能改變pPoint所指向對象的值//pPoint = &nConstValue2;           //錯誤,不能改變pPoint本身的值
const T&

對常量(const)的引用,又稱為常量引用,常量引用不能修改其邦定的對象。

int i = 5;const int constInt = 10;const int& rConstInt = constInt;    //正確,引用及邦定的值都是常量rConstInt = 5;                      //錯誤,不能改變引用所指向的對象

允許為一個常量引用邦定一個非常量對象、字面值,甚至是運算式;引用的類型與引用所指向的類型必須一致。

int i = 5;int& rInt = i;                      //正確,int的引用const int constInt = 10;const int& rConstInt = constInt;    //正確,引用及邦定的值都是常量const int& rConstInt2 = rInt;       //正確,用rInt邦定的對象進行賦值rInt = 30;                          //這時,rConstInt2、rInt、i的值都為30//rConstInt2 = 30;                  //錯誤,rConstInt2是常量引用,rConstInt2本身不能改變所指向的對象int i2 = 15;const int& rConstInt3 = i2;         //正確,用非常量的對象為其賦值const int& rConstInt4 = i + i2;     //正確,用運算式為其賦值,值為45i = 20;                             //此時i=20, rInt = 20, rConstInt4 = 45,說明rConstInt4邦定的是i + i2的臨時變數const int& rConstInt5 = 50;         //正解,用一個常量值為其賦值
const T*&與T *const&

指向常量對象的指標的引用,這可以分兩步來理解:1.const T*是指向常量的指標;2.const T*&指向常量的指標的引用。

const int nConstValue = 1;                      //常量對象const int nConstValue2 = 2;                     //常量對象const int* pConstValue = &nConstValue;          //指向常量對象的指標const int* pConstValue2 = &nConstValue2;        //指向常量對象的指標const int*& rpConstValue = pConstValue;         //指向常量對象的指標的引用//*rpConstValue = 10;                           //錯誤,rpConstValue指向的是常量對象,常量對象的值不可改變rpConstValue = pConstValue2;                    //正確,此時pConstValue的值等於pConstValue2//指向常量對象的指標本身是對象,引用可以改變邦定對象的值int nValue = 5;int nValue2 = 10;int *const constPoint = &nValue;                //常量指標int *const constPoint2 = &nValue2;              //常量指標int *const &rpConstPoint = constPoint;          //對常量指標的引用,邦定constPoint//rpConstPoint = constPoint2;                   //錯誤,constPoint是常量指標,指標本身的值不可改變*rpConstPoint = 20;                             //正確,指標指向的對象可以改變
在函數中的應用

我們直接從需求出來,假設有這樣一個資料結構:

typedef struct __Data{    int value;public:    __Data()        :value(0){}}Data;
1.希望傳入一個對象,又不想讓函數體修改這個對象。方式<1>
void Dealwith(const Data& data){    cout << data.value << endl;    //data.value = 5;       //錯誤,data是常量引用,不能改變其邦定的對象}

這種方式還有一個好處是只有在調用函數的時候會邦定對象,傳遞的是對象的引用,而不是對象,減少函數調用時對象賦值的花銷。

方式<2>
void Dealwith(const Data* pData){    cout << pData->value << endl;    //pData->value = 5;     //錯誤,pData是指向常量對象的指標,不能改變其指向的對象}

這種方式與void Dealwith(const Data& data)的功能相同

方式<3>
Data g_data(20);void Dealwith(const Data*& pData){    cout << pData->value << endl;    //pData->value = 5;     //錯誤,pData邦定的是指向常量對象的指標,常量對象的指標不能改變其指向的對象    pData = &g_data;        //正確,pData是[指向常量對象的指標]的引用,引用可改變其邦定的對象}

調用如下:

Data d(10);const Data* pData = &d;Dealwith(pData);cout << pData->value << endl;   //此時pData->value為20,d.value還是10

這種方式函數未改變傳入的對象的值,但可以返回另外一個對象的指標。注意返回的指標必須指向全域的對象,如果返回函數內定義的對象,退出函數範圍後,其指標將無效,這是非常危險的;如果Dealwith是成員函數,也可以返回指向成員的指標。

2.在類中的使用,返回一個類的成員,但不希望調用方修改這個成員。方式<1>
class MyData{public :    MyData(std::string name, Data data)    {        m_name = name;        m_data = data;    }    const Data* GetData()    {        return &m_data;    }private:    std::string m_name;    Data m_data;};

調用如下:

MyData mydata("", Data(100));const Data* pData = mydata.GetData();cout << pData->value << endl;   //pData->value = 100//pData->value = 50;            //錯誤,pData是指向常量對象的指向,不能改變其指向對象的值 
方式<2>

有人可能會問GetData也可以寫成這樣:

const Data& GetData(){    return m_data;}

這樣的話,調用方常常容易寫成這樣:

MyData mydata("", Data(100));Data data = mydata.GetData();   //這會有個賦值的過程,會把mydata.m_data賦給datacout << data.value << endl;     //data.value = 100data.value = 50;                //正確,data.value=50,但mydata.m_data.value還是100

這樣調用時會有一個結果賦值的過程,如果Data是一個複雜的類,會有較大的開銷,其效果與下面這種方式是一樣的:

Data GetData(){    return m_data;}

當然,如果調用方這樣使用是正確的:

const Data& GetData(){    return m_data;}
MyData mydata("", Data(100));const Data& data = mydata.GetData();    //這會有個賦值的過程,會把mydata.m_data賦給datacout << data.value << endl;             //data.value = 100//data.value = 50;                      //錯誤,data是一個對常量的引用,不能改變其邦定的對象

這對調用方的技術能力要求比較高,如果你是設計方,一定要盡量使介面簡單易用。

方式<3>

如果你要傳入一個Data進行一些處理,處理完後返回類的成員m_data,可如下實現:

void DoSomething(const Data*& pData){    if (pData != NULL)    {        // doto: 這裡實現你要處理的功能    }    pData = &m_data;}

如果您有什麼疑惑和想法,請在評論處給予反饋,您的反饋就是最好的測評師!由於本人技術和能力有限,如果本博文有錯誤或不足之處,敬請諒解並給出您寶貴的建議!


如果您有什麼疑惑和想法,請在評論處給予反饋,您的反饋就是最好的測評師!由於本人技術和能力有限,如果本博文有錯誤或不足之處,敬請諒解並給出您寶貴的建議!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.