1 標頭檔裡的const
const預設為內部串連(internal linkage),僅在本檔案內可見.
為了使const能夠被外部檔案所引用,必須明確把它定義成extern
extern const int x = 1;
這樣是是對常量做定義,而不是聲明.
聲明是這樣的 extern const int i; 表示在其它地方有定義一個常量i;
2 const的空間分配問題
1 通常c++編譯器並不為const建立儲存空間,將它的定義儲存在符號表裡,這個叫編譯期間的常量(可以用來給數組定義大小)
2 當extern是定義的一部分時,(同1中一樣, 是定義不是聲明),意味著不同的編輯單元可以引用它,所以它必須有儲存空間
3 當下文中有取常量的地址時,常量也要分配儲存空間.但這不妨礙編譯器知道它是常量,仍然可以用來定義數組的大小.
4 當const用於定義數組或者自訂類型時(書中用的是"彙總"aggregate這個詞),編譯器不會將一個彙總儲存在符號表中,因此要分配儲存空間,並且它不是一個編譯期間的常量.
例如
const int i[] ={1,2,3,4};float f[i[3]]; //Illegal
5 const在C語言中的意思是"一個不可改變的變數".在C語言中,const總是佔有儲存並且全域串連,因此不可以當作一個編譯期間的常量,
例如 :在c語言中,如下代碼是非法的
const int bufsize=100;int buf[bufsize];
6 總結: C++是否為常量分配儲存空間取決於如何使用.
如果僅僅只把一個名字用一個值代替(累似#define),就不分配儲存空間,
如果取常量地址 常量是彙總類型 將常量定義成extern ,就需要分配儲存空間.
只要不是彙總類型,就可以當作編譯期間常量使用
3 const指標
指向const的指標 const int *a; int const *b; (const在*左邊)
const指標
int *const c; (const在*右邊)
指向const的const指標 const int * const a; 或者 int const * const a;
4 賦值和類型檢查
不能將一個const對象的地址賦給非const指標
這個檢查主要在賦值和函數參數為指標時 進行檢查
這個規則有個例外:
char *cp = "howdy";
5 參數傳遞和傳回值
1 傳遞const 值
函數內參數不可變
2 返回const值
傳回值是內建類型時,const是無關緊要的,因為它總是一個值而不是一個變數, 建議去掉const
傳回值是自訂類型時,表示傳回值不可以做左值(不能被賦值,也不能被修改)
3 傳遞const指標
無論什麼時候傳遞一個地址給一個函數,都應該儘可能地用const修飾它,如果不這樣做,就不能以const指標參數的方式使用這個函數
4 返回const 指標
傳回值是const int *(指向const的指標) 只能被const int *指標接收
傳回值是const int * const(指向const的const指標) 能被const int * const 和const int *接收,都表示指向的目標不被改變
但不能做為左值
5 C++中出現的新情況: 臨時變數的地址傳給函數
一個總是const的臨時變數,它的地址可以被傳遞給函數.(使用引用,不能使用指標)
記住 臨時變數總是const
class X{};
X f(){return X();}
void g1(X &){}
void g2(const X&){}
int main()
{
g1(f()); //錯誤
g2(f()); //正確
}
為什麼C語言中做不到呢? 因為參數是指標時,必須明確指明地址
6 類中的const變數
1 普通const成員變數總會被分配儲存空間,並且不會在類聲明中賦初值 ,初值必須在建構函式的初始化列表中賦值.
所以普通const成員函數不能做為編譯時間常量使用
2 static const成員變數 可以看作編譯期間的常量,因為static標記的變數只初始化一次, static const變數在類定義中初始化
(回憶: 普通static變數是在類中聲明,類外定義的)
3 enum hack
不帶執行個體的enum
一個枚舉在編譯期間必須有值, 並且不會佔用類的儲存空間
class Bunch
{
enum{ size = 1000};
int buf[size];
};
4 const成員函數
1 const放在函數後面,代表該函數不會改變成員變數
2 聲明函數和定義函數 都要加const 否則認為是兩個不同函數
3 const對象只能調用const成員函數, const對象調用兩個同名函數時 調用的是const函數
4 在const成員函數中要如何改變成員變數?
在成員變數前面加 mutable 代表該變數可以在const成員函數中進行修改
5 const violate
violate代表"在編譯器認識的範圍外,該值可能改變" ,因此編譯器不能對該值做任何假定,每次都必須去該值所在的地址讀取
const violate變數表示 程式員不可以修改,但外部的代理程式可能修改的變數.