c++中的引用類型和const
C++中的引用類型
先看一段代碼:
int ival = 1024; int &refVal = ival; // ok: refVal refers to ival int &refVal2; // error: a reference must be initialized int &refVal3 = 10; // error: initializer must be an object引用需要注意的點:
1.引用就是變量的另一個名字,常量都不行;
2.定義引用時必須用與之同類型的變量初始化,初始化後就不能改變他的值了;
3.引用不占用內存。
c++中的const
const用於普通變量
void main(void) { int x = 4; // 定義為變量 const int y = 5; // 定義為常量,跟int const y = 5;一樣 x = y; // 給變量x賦值合法 //y = x; // 給常量y賦值出錯 }
用const修飾的變量在其作用域內會變成常量,不允許改變其值.
一、const用於指針
這個確實比較蛋疼。const位置不同意義也不同。
1. 指針本身是常量不可變
(char*) const pContent;
char * const pContent;
const (char*) pContent;
這個時候可以看到const修飾的其實是pContent;
2.指針所指向的內容是常量不可變
const (char) *pContent;
const char *pContent;
(char) const *pContent;
char const *pContent;
可以看到const 修飾的是*pContent,修飾的是pContent所指向的變量。
3. 兩者都不可變
const char* const pContent;
這個很好理解了。
二、const用於函數參數
被修飾的函數參數在函數體內不能改變其值。
void function(const int Var); //傳遞過來的參數在函數內不可以改變(無意義,因為Var本身就是形參) void function(const char* Var); //參數指針所指內容為常量不可變 void function(char* const Var); //參數指針本身為常量不可變(也無意義, 因為char* Var也是形參)
三、const修飾類對象/對象指針/對象引用
const修飾類對象/對象指針/對象引用 表示該對象為常量對象,其中的任何成員都不能被修改。
const修飾的對象,該對象的任何非const成員函數都不能被調用,因為任何非const成員函數會有修改成員變量的企圖。
四、const修飾成員變量/成員函數
const修飾類的成員常量,不能被修改,同時它隻能在初始化列表中賦值。
class A { … const int nValue; //成員常量不能被修改 … A(int x): nValue(x) {}; //隻能在初始化列表中賦值 }const修飾類的成員函數,表示該成員函數不能修改類中任何非const成員函數。
class A { … void function()const; //常成員函數, 它不改變對象的成員變量. 也不能調用類中任何非const成員函數。 }五、 const常量與define宏定義的區別
(1) 編譯器處理方式不同
define宏是在預處理階段展開。
const常量是編譯運行階段使用。
(2) 類型和安全檢查不同
define宏沒有類型,不做任何類型檢查,僅僅是展開。
const常量有具體的類型,在編譯階段會執行類型檢查。
(3) 存儲方式不同
define宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內存。
const常量會在內存中分配(可以是堆中也可以是棧中)。
const在c和c++中的區別
C++中的const正常情況下是看成編譯期的常量,編譯器並不為const分配空間,隻是在編譯的時候將期值保存在名字表中,並在適當的時候折合在代碼中.所以,以下代碼:
#include <iostream> using namespace std; int main() { const int a = 1; const int b = 2; int array[ a + b ] = {0}; for (int i = 0; i < sizeof array / sizeof *array; i++) { cout << array << endl; } }在可以通過編譯,並且正常運行.但稍加修改後,放在C編譯器中,便會出現錯誤:
#include <stdio.h> int main() { int i; const int a = 1; const int b = 2; int array[ a + b ] = {0}; for (i = 0; i < sizeof array / sizeof *array; i++) { printf("%d",array); } }錯誤消息:
c:\test1\te.c(8): error C2057: 應輸入常數表達式
c:\test1\te.c(8): error C2466: 不能分配常數大小為 0 的數組
出現這種情況的原因是:
在C中,const是一個不能被改變的普通變量,既然是變量,就要占用存儲空間,所以編譯器不知道編譯時的值.而且,數組定義時的下標必須為常量.
在C語言中:
const int size;
這個語句是正確的,因為它被C編譯器看作一個聲明,指明在別的地方分配存儲空間.但在C++中這樣寫是不正確的.C++中const默認是內部連接,如果想在C++中達到以上的效果,必須要用extern關鍵字.
C++中,const默認使用內部連接.而C中使用外部連接.
內連接:編譯器隻對正被編譯的文件創建存儲空間,別的文件可以使用相同的表示符
或全局變量.C/C++中內連接使用static關鍵字指定.
外連接:所有被編譯過的文件創建一片單獨存儲空間.一旦空間被創建,連接器必須解
決對這片存儲空間的引用.全局變量和函數使用外部連接.通過extern關鍵
字聲明,可以從其他文件訪問相應的變量和函數.
************************C++代碼****************************** header.h const int test = 1; test1.cpp #include #include "header.h" using namespace std; int main() { cout << "in test1 :" << test << endl; } test2.cpp #include #include "header.h" using namespace std; void print() { cout << "in test2:" << test << endl; }
以上代碼編譯連接完全不會出問題,但如果把header.h改為:
extern const int test = 1;
在連接的時候,便會出現以下錯誤信息:
test2 error LNK2005: "int const test" (?test@@3HB) 已經在 test1.obj 中定義
因為extern關鍵字告訴C++編譯器test會在其他地方引用,所以,C++編譯器就會為test創建存儲空間,不再是簡單的存儲在名字表裏麵.所以,當兩個文件同時包含header.h的時候,會發生名字上的衝突.
此種情況和C中const含義相似:
header.h
const int test = 1;
test1.c
#include
#include "header.h"
int main()
{
printf("in test1:%d\n",test);
}
test2.c
#include
#include "header.h"
void print()
{
printf("in test2:%d\n",test);
}
錯誤消息:
test3 fatal error LNK1169: 找到一個或多個多重定義的符號
test3 error LNK2005: _test 已經在 test1.obj 中定義
C++中,是否為const分配空間要看具體情況.
如果加上關鍵字extern或者取const變量地址,則編譯器就要為const分配存儲空間.
C++中定義常量的時候不再采用define,因為define隻做簡單的宏替換,並不提供類型檢查.
最後更新:2017-04-03 16:59:42