const關鍵字總結

在C語言中

const是C語言中總結
1.修飾的變量,使其具有常屬性,使變量的值不能直接被改變。但是可以通過指針來間接的修改變量的值。
2.便於進行類型檢查(在編譯時進行類型檢查),使編譯對處理內容有更多的瞭解,保護被修飾的東西,防止被意外修改,增強程序的健壯性。
3.方便的進行參數的調整和修改(類似於宏定義)
作用1說明:
修飾的變量,使其具有常屬性,使變量的值不能直接被改變。但是可以通過指針來間接的修改變量的值
例如:

const int t=10;
//在以後的代碼中,程序不可直接對i進行修改
//但是可通過指針來間接的修改i變量中存的值

t=2;   //會報錯

int *p=(int *)&t;
*p=2;   //在此處就將i中的值存成2了

const修飾指針變量:

int main()
{
    int a = 10;
    const int *p = &a;     //const修飾int *,即p的指向,因而p指向的內容即通過pa解引用後不能被修改,但是p中存的內容可以改變,即p的指向可以改變
    int  * const q=&a;       //const修飾*,即q變量,因而q裏存的內容不能變,即q的指向不能改變,但是q指向的內容即a中的內容可以修改。
    p++;//正確
    (*p)++;//錯誤
    q++;//錯誤
    (*q)++;//正確
    return 0;
}

所以看const修飾誰,要看const右面有什麼
比如:
int **const* p; 則通過*p來修改對應的內容則報錯

int **const** p; 則通過**p來修改內容則會報錯

通過const的特性,const可以在很多地方派上用場
比如在傳參時,不想通過函數來改變實參值,在傳實參地址時,形參接收在前可加const修飾,這樣就不會在函數裏通過解引用來修改實參值了

  • 在C語言中,const不用來修飾函數,原因看C++的用法

在C++中

在c++中:
1.const修飾變量的用法和作用與c語言一樣,但是有一點不同

 #include <iostream>  
 using namespace std;  

 int main()  
  {  
     const int a = 1;  
     int* p = (int *)(&a);  
     *p = 2;  
     cout << "value of p: " << *p << endl;  
     cout << "value of a: " << a << endl;  
     cout << "address of p: " << p << endl;  
     cout << "address of a: " << &a << endl;    
     return 0;  
 } 
 輸出
 /*value of p: 2
value of a: 1
address of p: 0x7fbffff7fc
address of a: 0x7fbffff7fc

由答案可知,a並沒有像c語言中一樣,被p修改爲2,這是爲什麼呢?
原因: const int a其實是保存在符號表中,無內存地址,但自己對a進行&a,那麼編譯器會爲a分配一個地址,但取a的值依然是從符號表中取值,而用指針int *p=&a;
*p=4這個值是改變a的內存所表示值,不會改變符號表中a的值。

  #include <iostream>  
  using namespace std;  
  const int a = 3;       //此時a是全局變量
  int main()  
  {  
      //const int a = 3;     
     int* p = const_cast<int*>(&a);  
     *p = 4;  
     cout << "value of p: " << *p << endl;  
     cout << "value of a: " << a << endl;  
     cout << "address of p: " << p << endl;  
     cout << "address of a: " << &a << endl;  

     return 0;  
 }  

輸出結果
const關鍵字總結
會發生如此運行時錯誤
由此可見,在c++中全局const變量和局部const變量的編譯器處理的方法是不一樣的。因爲全局const變量是不分配內存地址的,它編譯器放置在符號表中作爲編譯期常量,全局const變量放在只讀數據段中,受到只讀數據段的權限保護,當你修改一個只讀數據段中的內容時,會得到一個運行時錯誤。而局部const變量是放在堆棧之中,因爲在內存中有地址,通過修改地址中的值可以達到修改const所指內存中值的目的。

2.此外,在c++中,const還可用來修飾成員函數,其用法是放在形參列表之後,
用來修飾隱式傳入構造函數中的this指針,表明在函數調用的過程中,不可對this指向的內容進行修改,即不可修改調用這個構造函數對象中的內容。
被const修飾的成員函數,稱作爲const類型的成員函數
例如:

class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
        cout << "Date(int,int,int):" << this << endl;
    }

    // 在const成員函數中,不能修改類的任何成員變量
    void PrintDate()const
    {
        //_year++;
        //即this->_year++;      會報錯
        // 在函數被修飾後,this的類型爲 const Date* const     (因爲this指針本來就是const型的this不可修改指向,後面的const表明this指向裏的內容也不可修改) 
        _day++;    //√
        cout << _year << "-" << _month << "-" << _day << endl;
    }

private:
    int _year;
    int _month;
    mutable int _day;    //在成員變量名前加mutable關鍵字後,成員函數即使加const也可修改_day的值
};

int main()
{
Date d1;
d1. PrintDate();
}

用const修飾成員函數有以下注意事項:
1>const不可修飾其他類外函數(對有this的函數纔有用)。不可調用構造函數,因爲構造函數目的就是要修改成員變量。
2>const對象不可以調用非const成員函數。因爲普通成員函數是可以修改成員變量的,如果允許修改,拿不可修改的const對象就會被修改了,不安全。
3>非const對象可以調用const成員函數。因爲普通變量可讀可寫,const函數只允許對調用對象進行讀,因此沒有什麼不可。
4>const成員函數不可以調用非const成員函數。普通函數可對對象進行修改,在調用普通函數時可能會修改對象,因此const成員函數不能調用非const成員函數。
5>非const成員函數可以調用const成員函數

const 變量與 define 宏定義的區別:

(1) 編譯器處理方式不同
define宏是在預處理階段展開。
const常量是編譯運行階段使用。
(2) 類型和安全檢查不同
define宏沒有類型,不做任何類型檢查,僅僅是展開。
const常量有具體的類型,在編譯階段會執行類型檢查。
(3) 存儲方式不同
define宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內存。
const常量會在內存中分配(可以是堆中也可以是棧中)
const修飾可以節省空間,避免不必要的內存分配(與宏定義的本質區別)

宏的優點:
1.增強代碼的複用性。
2.提高性能。
缺點:
1.不方便調試宏。(因爲預編譯階段進行了替換)
2.導致代碼可讀性差,可維護性差,容易誤用。
3.沒有類型安全的檢查

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