天天看點

CONST關鍵字筆記

const修飾的值并不是常量,而是隻讀的變量。其值在編譯時不能被使用,因為編譯器在編譯時不知道其存儲的内容。

C++ 裡 const 變量一般預設 static 連接配接方式

也就是其它 .cpp 檔案看不到,是以用 extern 聲明也沒用

可将 const 變量的聲明放在 .h 檔案裡,需要使用此常量的 .cpp 都 #include 它

編譯器通常不為普通const隻讀變量配置設定存儲空間,而是将它們儲存在符号表中,這使得Tam它成為一個編譯期間的值,沒有了存儲和讀記憶體的操作,使它的效率很高。

#define M 3        //宏常量

const int N = 5;  //此時未将N 放入記憶體

......

int i = N;  //此時為N 配置設定記憶體,之後不再配置設定

int I = M;  //預編譯期間進行宏替換,配置設定記憶體

int j = N;  //沒有記憶體配置設定

int J = M;   //再次進行宏替換,再次配置設定記憶體

const定義的隻讀變量從彙編角度上看,隻是給出了對應的記憶體位址,而不是像 #define一樣,給出的是立即數。是以,const定義的隻讀變量在程式運作過程中隻有一份copy,因為他是全局的隻讀變量,放在靜态區。#define 宏實在預編譯階段進行替換,const修飾的隻讀變量是在編譯時确定其值。

?

下面的代碼在存為C檔案在VC6.0編譯器下編譯是錯誤的!為什麼?

#include<stdio.h>

void main()

{

const int bufsize = 10 ;

char buf[bufsize] = {'a','b','c'};//error C2057:expected constant expression

//error C2466: cannot allocate an array of constant size 0

printf ("%S",buf);

}

在編譯時,編譯器并不知道const的值,它隻是一個“運作時常量”。不是放在符号表裡的。(編譯原裡的知識這裡就不多講了!)

然而把上面的代碼改成CPP檔案在VC6.0編譯器下編譯是通過的。

通常,C++編譯器不為const建立存儲空間,而是把它儲存在“符号表”裡,即“編譯時常量”。預設情況下,C++中的const是内部連接配接的,也就是說,const僅在const被定義過

?

的檔案裡才是可見的。(是以,不用擔心名字沖突)當定義一個const時,必須賦一個值給它,除非用extern做出了清楚的說明。當用extern說明了const時,編譯器會強制為const

?

配置設定空間,而不是儲存在符号表中。

const修飾的隻讀變量必須在定義的同時初始化。

用如下方法可以修改const常量,但是如果将const int i=0;放到main函數之外,作為全局變量,則施行的時候會報錯。

#include<stdio.h>

main()

{

const int i=0;

int *p=&i;

*p=3;

printf("%d",i);

}

類中的常量:

在類中,const資料成員隻在某個對象生存期内是常量,而對于整個類而言确實可變的,因為類可以建立多個對象,不同的對象其const資料成員的值可以不同。

不能在類聲明中初始化const資料成員,以下用法錯誤,因為類的對象還未被建立時,編譯器不知道SIZE的值為多少:

class A

{

  const int SIZE = 100;

  int array[SIZE];

};

const資料成員的初始化隻能在類構造函數的初始化中進行,例如:

class A

{

  A(int size);//構造函數

  const int SIZE;

};

A::A(int size):SIZE(size)

{

}

A a(100);//對象a的size值為100

A b(200);//對象b的size值為200

要建立在整個類中都恒定的常量,可用枚舉常量來實作。但枚舉常量是整數,不能表示浮點數

class A

{

  enum {SIZE1 = 100,SIZE2 = 200};

  int array1[SIZE1];

  int array2[SIZE2]; 

}

------------------

用const提高函數健壯性

1、const修飾函數參數

如果參數作輸出用,不管是什麼資料類型,也不管是采用指針傳遞還是引用傳遞,都不能加const,否則該參數将失去輸出功能。

如果參數作為輸入:

     值傳遞:形參變動不會影響實參,是以無需保護。不需要加const修飾。無需将void Func1(int x)寫成void Func1(const int x),也無需将void Func2(A a)寫成void Func2(const A a),A為使用者自定義的資料類型。

  引用傳遞:對于非内部資料類型的參數而言,像void Func2(A a)這樣聲明的函數效率較低,因為函數體内将産生A類型的臨時對象用于複制參數a,而臨時對象的構造、複制、析構過程都耗費時間。為了提高效率,可以将函數聲明改為void Func2(A  &a),引用傳遞不産生臨時對象。但可能改變參數a,是以可以改為void Func2(const A &a) ,但内部資料類型就不需要如此修改,因為int等類型不存在構造析構的過程,值傳遞和引用傳遞的效率相當。

  指針傳遞:加const修飾可以防止意外改動該指針。

void stringcopy(char * strdestination , const char strsource); //輸出參數不可加const

用const修飾函數的傳回值

  如果給“指針傳遞”方式的函數傳回值加const修飾,那麼函數傳回值的内容不可以被修改,而且隻能被賦給加const修飾的同類型指針:

const char *getstring(void);

char *str = getstring();//錯誤

const char *str = getstring();//正确

  如果函數傳回采用“值傳遞”,由于函數會把傳回值複制到外部臨時存儲單元,加const無作用:

不要把int getint(void)寫成const int getint(void)

不要把A getA(void)寫成const A getA (void)

-----------------------------------------------------

const修飾一般變量:

int const i = 2;或 const int i = 2;

修飾數組

int const a[5] = {1,2,3,4,5};

const int a[5] = {1,2,3,4,5};

修飾指針

const int *p;//p可變,p指向的對象不可變  常量指針

int const *p;//p可變,p指向的對象不可變 常量指針

int *const p;//p不可變,p指向的對象可變 指針常量

const int *const p;//指針p和p指向的對象都不可變。

修飾函數參數

修飾函數的傳回值