改編自
http://baike.sogou.com/v64494396.htm?fromTitle=CONST
http://blog.csdn.net/lihao21
http://blog.sina.com.cn/s/blog_79b01f6601018xdg.html
- const與#define宏定義的對比:
const可以節省空間,避免不必要的內存分配。(const是為了消除#define的缺點而產生的)
例如:
#define PI 3.14159 //常量宏
double I=PI; //編譯期間進行宏替換,分配內存
double J=PI; //再進行宏替換,又一次分配內存!
const double Pi=3.14159; //此時并未將Pi放入RAM中
double i=Pi; //此時為Pi分配內存,以后不再分配!
double j=Pi; //沒有內存分配
const定義常量從匯編的角度來看,只是給出了對應的內存地址,而不是像#define一樣給出的是立即數,所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內存中有若干份拷貝。
- const常用用法:左定值,右定向
1)const在前面
const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可變
const char* const pContent; //pContent和*pContent都是const
2)const在后面,與上面的聲明對等
int const nValue; //nValue是const
char const * pContent; //*pContent是const, pContent可變
char* const pContent; //pContent是const,*pContent可變
char const* const pContent; //pContent和*pContent都是const
const只修飾其后的變量,至于const放在類型前還是類型后并沒有區別。如:const int a和int const a都是修飾a為const。
3)指針指向的變量的值不能變,指向可變(左定值)
int x = 1;
int y = 2;
const int* px = &x;
int const* px = &x; //這兩句表達式一樣效果
px = &y; //正確,允許改變指向
*px = 3; //錯誤,不允許改變指針指向的變量的值
4)指針指向的變量的值可以改變,指向不可變(右定向)
int x = 1;
int y = 2;
int* const px = &x;
px = &y; //錯誤,不允許改變指針指向
*px = 3; //正確,允許改變指針指向的變量的值
5)指針指向的變量的值不可變,指向不可變
int x = 1;
int y = 2;
const int* const px = &x;
int const* const px = &x;
px = &y; //錯誤,不允許改變指針指向
*px = 3; //錯誤,不允許改變指針指向的變量的值
6)
typedef char * pStr;
char string = "bbc";
const char *p1 =" string"; //1式
const pStr p2 =" string"; //2式
p1++;
p2++;
答案:const使用的基本形式: const type m;限定m不可變。替換基本形式中的m為1式中的*p1,替換后const char *p1;限定*p1不可變,當然p1是可變的,因此問題中p1++是對的。替換基本形式中的type為2式中的pStr,替換后const pStr m;限定m不可變,題中的pStr就是一種新類型,因此問題中p2不可 變,p2++是錯誤的。
7)在c中,對于const定義的指針,不賦初值編譯不報錯,
int* const px;這種定義是不允許的。(指針常量定義的時候對其進行初始化,右定向,必須指定指針指向)
int const *px;這種定義是允許的。(常指針可以再定義的時候不初始化,左定值,可以不賦初值)
- const成員函數: 若將成員成員函數聲明為const,則該函數不允許修改類的數據成員。
在C++中,只有被聲明為const的成員函數才能被一個const類對象調用。
const Screen blankScreen;
blankScreen.display(); // 對象的讀操作
blankScreen.set(‘*’); // 錯誤:const類對象不允許修改
1)值得注意的是,把一個成員函數聲明為const可以保證這個成員函數不修改數據成員,但是,如果據成員是指針,則const成員函數可以修改指針指向的對象。
2)const成員函數可以訪問非const對象的非const數據成員、const數據成員,也可以訪問const對象內的所有數據成員;
3)非const成員函數可以訪問非const對象的非const數據成員、const數據成員,但不可以訪問const對象的任意數據成員;
4)作為一種良好的編程風格,在聲明一個成員函數時,若該成員函數并不對數據成員進行修改操作,應盡可能將該成員函數聲明為const 成員函數。
- 在const成員函數中,用mutable修飾成員變量名后,就可以修改類的成員變量了。
- 類中的常量:有時我們希望某些常量只在類中有效。由于#define定義的宏常量是全局的,不能達到目的,于是想當然地覺得應該用const修飾數據成員來實現。const數據成員的確是存在的,但其含義卻不是我們所期望的。const數據成員只在某個對象生存期內是常量,而對于整個類而言卻是可變的,因為類可以創建多個對象,不同的對象其const數據成員的值可以不同。
不能在類聲明中初始化const數據成員。以下用法是錯誤的,因為類的對象未被創建時,編譯器不知道SIZE的值是什么。
class A
{…
const int SIZE = 100; // 錯誤,企圖在類聲明中初始化const數據成員
int array[SIZE]; // 錯誤,未知的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
怎樣才能建立在整個類中都恒定的常量呢?別指望const數據成員了,應該用類中的枚舉常量來實現。例如
```
class A
{…
enum { SIZE1 = 100, SIZE2 = 200}; // 枚舉常量
int array1[SIZE1];
int array2[SIZE2];
};
枚舉常量不會占用對象的存儲空間,它們在編譯時被全部求值。枚舉常量的缺點是:它的隱含數據類型是整數,其最大值有限,且不能表示浮點數(如PI=3.14159)。sizeof(A) = 1200;其中枚舉部長空間。
```enum EM { SIZE1 = 100, SIZE2 = 200}; // 枚舉常量 sizeof(EM) = 4;```