一、關鍵字Const作用:
1.可以定義const常量,具有不可變性。
例如:const int Max=100; Max++會産生錯誤;
2.便于進行類型檢查,消除了一些隐患。const常量有資料類型,而宏常量沒有資料類型。編譯器可以對前者進行類型安全檢查,而對後者隻進行字元替換,沒有類型安全檢查,并且在字元替換時可能會産生意料不到的錯誤。
例如: void f(const int i) { .........} //編譯器就會知道i是一個常量,不允許修改;
3.可以避免意義模糊的數字出現,同樣可以很友善地進行參數的調整和修改。 同宏定義一樣,可以做到不變則已,一變都變!如1.中,如果想修改Max的内容,隻需要:const int Max=you want;即可!
4.可以保護被修飾的東西,防止意外的修改,增強程式的健壯性。 還是上面的例子,如果在函數體内修改了i,編譯器就會報錯;
例如: void f(const int i) { i=10; } //error!
5.為函數重載提供了一個參考;
例如:class A
{
......
void f(int i) {......} //一個函數
void f(int i) const {......} //上一個函數的重載
......
};
6. 可以節省空間,避免不必要的記憶體配置設定。const定義常量從彙編的角度來看,隻是給出了對應的記憶體位址,而不是像#define一樣給出的是立即數,是以,const定義的常量在程式運作過程中隻有一份拷貝,而#define定義的常量在記憶體中有若幹份拷貝。
例如:
#define PI 3.14159 //常量宏
const double Pi=3.14159; //此時并未将Pi放入RAM中 ......
double i=Pi; //此時為Pi配置設定記憶體,以後不再配置設定!
double I=PI; //編譯期間進行宏替換,配置設定記憶體
double j=Pi; //沒有記憶體配置設定
double J=PI; //再進行宏替換,又一次配置設定記憶體!
7. 提高了效率。 編譯器通常不為普通const常量配置設定存儲空間,而是将它們儲存在符号表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀記憶體的操作,使得它的效率也很高。
二.Const限定符在C/C++中差別:
1.C語言中的常變量的不可以定義數組。因為C中的常變量和變量唯一的差別是不能作為左值,其他性質都和變量一樣。eg: 在.C中,有三種修改const常變量值的方式:
int b=20; const int a= 10;
1) int *p=&a; *p=20;
-
2) _asm
{mov dword[ebp-8] 14h}
3) *(&b-1)=20;
C語言中可以引用外部const變量聲明/定義,會生成一個global符号。連結器在連接配接的時候,隻看g符号。而在其前加上static,就會變為local。除了外部常量,外部變量産生的符号也是g。
2 . C++中的常變量可以作為數組的下标,可以定義數組。常變量是常量。但是在某些情況下,會退化為 變量。
C++中常變量在編譯階段所有出現常量名字的地方會被常量值替換,但不會替換類似&a表達式中的a,當a是const常量時。而C中的常變量在編譯階段并不會被替換。
C++中不可以引用外部檔案定義的常量,因為産生的是local符号 ;
因為替換的時候隻能在目前檔案中替換。如果要能被外部引用到,在變量定義時加上一個extern,就可将其連結屬性變為global.
當一個常變量的初始值為外部定義的值時,此時常量就會退換成常變量。因為編譯階段不知道初始值,連結時才知道有這個符号的定義,運作時才會指派。那麼常量的所有彙編也都會變成和變量一樣。
三.Const限定符與&.*的結合:
1.const 和一級指針的結合 :
當const修飾一個變量名時,并不是意味着這個變量所占的記憶體是const,而是不能通過這個名字對其修改或洩露常量記憶體位址或引用。例如:
常見用法:
int a = 10;
const int *p = &a;
int *q = p;
4.const和二級指針的結合,例如:
1)常見錯誤:
int a = 10;
int *p = &a;
const int **q = &p;
int** -> const int **: const修飾的哪個變量就先改變哪一邊 *q<->p這裡的*p會洩露常量位址,是以出錯!如果,**q<->*p,将一個常量的值放入const修飾的變量中,則不會出錯。
2)經過修改之後:
int a = 10;
int *p = &a;
const int * const *q = p;//這裡組織*q被非法修改;
3)又如:
int a = 10;
int *p = &a;
int * const *q = &p;//**q<->*p也沒有問題;
4)當const和指針結合時,若const右邊無指針時,有沒有const無差別。是以不能構成重載。
void func(const int a)
{
}
void func(int b)
{
}
5)當對實參的值有影響時,才會構成重載。下面這個就可以構成重載。
void func(const int* a)
{
}
void func(int* b)
{
}
6)類型轉換總結:
錯誤的類型轉換:會把常量的位址放在一個普通的指針裡面!!
int * - > const int * --> right
const int * -> int * --> error!
int **- > const int ** <相當于> int *& -> const int * --> error!
const int ** -> int ** <相當于> const int *& -> int * --> error!
int* const * -> int ** -->error!
//const跟多級指針結合,必須兩邊都給修飾!!
5.引用:
引用就是一個指針,無論是什麼時候占四個位元組。
C++中一個空類占一個位元組(不同編譯器不一樣,有的不可以定義)
struct
{
char a;
char b;
char c;
}data;
//sizeof(data)=3
6.const 跟 */&的結合:
引用在使用時自動解引用
sizeof(p)=16 (引用了一個數組)
//sizeof(p)=16
如果不好直接寫引用,可以在寫的時候可以先寫成一個函數指針(引用數組名),然後改為引用。
在這個記憶體位址上寫一個四位元組的整數10
int p=(int )0x0018ff44
*p=10;
//要想定義一個引用變量,如果右邊位址不可取,就弄一個常引用
int const &p=(int )0x0018ff44
*p=10;
下面的錯誤,是vc的一個bug,編譯器檢測不出淚,vs可以檢測出來
相當于将int**轉化為一個const int *,從引用角度來看,p和q是同一塊記憶體,int 和const int *不能是同一塊記憶體。是以錯誤 !
錯誤, p是一個const常量,由于*q=p,是以最後一句應改為
int *const*q=&p;
//由于*q<->p,是以給*q賦一個整型常量的位址也就是相當于給p附一個整型常量位址,但是這樣會使得整型常量位址洩露,是以修改的辦法有兩種防止位址洩露被修改:
1)
//讓*p為常量,防止它被指派。
2)
//禁止*q的改變,達到給p指派的目的
7.C++11中出現了左引用和右引用。
引用占記憶體,四個位元組,&b列印出來就是a的位址,引用位址就是所引用變量的位址,使用引用時,自動解引用。
1)左值引用
左值引用隻能綁定左值,不能綁定右值.
如下:
[cpp] view plain copy
- int x = 1;
- int &y = x; //綁定左值,正确
- int &z = 2; //綁定右值2,編譯錯誤
但是可以将右值綁定到一個const左值引用(這是一個例外)
如:
[cpp] view plain copy
- //右值綁定到const左值引用
- nt const &i = 28; //正确
在右值引用誕生之前,為了傳遞臨時對象到函數中以引用,這将允許實參隐式轉換到形參類型,如下:
[cpp] view plain copy
- void print(std::string cosnt& s) {}
- print("hello"); //“hello”字元串是臨時字元串對象,也是右值
2)右值引用
右值引用隻能綁定右值,不能綁定左值.使用兩個&&表示右值引用.
如:
[cpp] view plain copy
- int&& i = 8;
- int j = 18;
- int&& k = j; //編譯錯誤
通過使用函數重載來決定函數參數是左值/右值,重載函數參數設定為左值引用和右值引用.
[cpp] view plain copy
- void fun_reference(int& a)
- {
- std::cout << "左值引用:" << a << std::endl;
- }
- void fun_reference(int&& a)
- {
- std::cout << "右值引用:" << a << std::endl;
- }
- int main()
- {
- int x = 8;
- fun_reference(x); //輸出左值引用:8
- fun_reference(18); //輸出右值引用:18
- return 0;
- }
[就暫且先總結這麼多吧,水準跟見識也有限,還望大家多多批評指正!!]