C++基本內置類型有bool(1個字節)、char(1個字節)、wchar_t(2個字節)、short(2個字節)、int(4個字節)、long(4個字節)、float(4個字節)、double(8個字節)、long double(8個字節)。基本內置類型的存儲空間依機器而定。c++標準規定了每一個算術類型的最小存儲空間。ios
變量名,即變量的標識符,由字母、數字和下劃線組成變量名必順以字母或下劃線開頭,而且區分大小寫字母:C++的c++
的標識符都是大小寫敏感的。程序員
默認的全局變量有默認值,局部變量則被賦予任意值,爲安全起見,不管全局或者局部變量都要初始化。數組
const int MaxSize = 100; //定義一個常量 MaxSize = 59;//試圖修改MaxSize常量,這一句在編譯的時候就要出錯
const對象在文件默認爲局部變量,也就是說,若是你想在其它文件裏使用這個const變量,你必需在定義的時候前面加安全
//file1.cpp extern const int MAX_COUNT = 20; //定義和初始化並聲明爲extern //file2.cpp extern const int MAX_COUNT; //使用MAX_COUNT常量從file1.cpp文件中
注:非const變量默認是全局變量(在頭文件中)。所以不須要在變量前面添加extern符號函數
引用(reference)就是對象的另外一個名字。在實際程序中,引用主要用做函數的形式參數。引用必需用與該引用同類型的對象初始化,如:url
int ival = 1024;//ok int &refval = ival;//ok int &refVal2; //錯誤,引用必需初始化。 Int &refVal3 = 10; //錯誤,初始化必需是一個對象
前面說過,引用其實就是對象的別名,所以在對一個引用操做時,實質是在對引用的那個變量進行操做。spa
typedef能夠用來定義類型的同義詞,如:操作系統
typedef double WAGES; WAGES hourly;
默認狀況下,枚舉的第一個成員賦值爲0,後面的每一個枚舉成員賦的值比前面的值大1。指針
enum Week{ Sun,Mon=5,Tue,Wed};
在Week枚舉中,Sun默認爲0,Mon = 5,Tue=6,Wed=7。
定義
int a[10]; char ch[10]; double dArray[3];
任何數組,不管是靜態聲明的仍是動態建立的,其全部元素在內存中都是連續字節存放的,也就是說保存在一大塊連續的內存區中。
初始化
int a[4]={8,9,5,3}; int b[]={7,9,2};
或者
int elem[3]; for(int i=0; i<3; i++) { elem[i]=i+1; }
數組不容許直接賦值變量,所以在數組copy時要for循環數組重的每個元素。如:
int b[]=a;//這裏是不容許的
初始化
指針進行初始化或賦值只能使用如下四種類型的值:
1)0常量表達式(請用NULL值初始化)
2)類型匹配的對象的地址
3)另外一個對象以後的下一地址
4)同類型的另外一個有效指針
int *p = 0; //把p指針初始化爲0 int ival=2; p = &ival;//把p初始化爲類型匹配的對象的地址 int* p2 = p; //把p2初始化爲同類型的另外一個有效指針
注意:避免使用未初始化的指針,不少運行時錯誤都源於使用了未初始化的指針。
void*指針
C++提供了一種特殊的指針類型void*,它能夠保存任何類型對象的地址,如:
double obj = 3.24; double *pd = &obj; void *pv = &obj; pv = pd;
void*指針只支持幾種有限的操做:與另外一個指針進行比較;向函數傳遞void*指針或從函數返回void*指針;給另外一個void*指針賦值。不容許使用void*指針操縱它所指向的對象。
指針和引用的比較
使用引用(reference)和指針均可間接訪問另外一個值,但它們之間有兩個重要區別。
1)引用老是指向某個對象:定義引用時沒有初始化是錯誤的。
2)賦值行爲的差別:給引用賦值修改的是該引用所關聯的對象的值,而並非使引用與另外一個對象關聯。引用一經初始引用一經初始化,就始終指向同一個特定對象
指針的算術運算
#include <string> #include <iostream> using namespace std; //main函數 void main() { int a[6] = {36, 15, 345, 63, 43, 344}; int *pStart = a; int *pEnd = pStart + 6;//指向該數組末端的下一單元 //計算元素的個數 int n = pEnd - pStart; //打印數組 for(int i=0; i<n; i++) { cout << *pStart++ <<" "; } cout << endl; }
指針和const限定符
1)指向const對象的指針
#include <string> #include <iostream> using namespace std; //main函數 void main() { double pi = 3.14; const double *cptr = π //*cptr = 5;//指針不能改變其對象的值,所以是錯誤的 }
2)const指針
#include <string> #include <iostream> using namespace std; //main函數 void main() { double val = 1.4; double *const cptrVal = &val; double val2 = 2.5; //cptrVal = &val2;//const指針不能修改 }
在有些狀況,編譯沒法知道數組的大小;好比:讀一個文件,這個時候咱們開多大的buf來裝數據呢?答案是不知道的。
所以咱們須要在知道一個文件的大小後,在分配一個數組來裝數據,建立動態數組就能解決這種狀況。
咱們能夠像這樣去定義,如:
int *pBuf = new int[1024];
建立動態數組,不是沒有代價的,你new了一個新的數組,卻沒有delete掉數組,那麼你就有內存泄漏的風險,所以在
不須要的時候要調用delete[] 刪除數組,如:
if(pBuf)
{
delete[] pBuf
pBuf = NULL;
}
嚴格地說,C++中沒有多維數組,一般所指的多維數組其實就是數組的數組。
先來看看二維數組的定義和初始化,咱們來看一段代碼
int a[2][3];//數組的定義
int b[2][3] = {{0,1,2},{4,5,6}}; //數組的初始化
int c[2][3] = {0,1,2,3,4,5};//數組的初始化
上面的代碼演示了二維數組的定義和初始化
注意,咱們在使用二維數組的時候要按照「先行後列」的方式來訪問,而不是先列後行。這是由於咱們假設一個內存頁爲4096字節,而且定義一個數組b[128][1024],其
列數爲1024(即每一行的元素剛好佔用一頁),當你用「先行後列」方式時,外層循環走過每一行,正好走完一頁,沒
有發生頁面調度。當循環進入下一行時操做系統從外存調入下一頁,所以,咱們能夠知道,遍歷完後次數最多爲128次。可是你用「先列後行」方式來遍歷的話,可能在遍歷完後頁面調度交數變成了1024*128。這將大大下降效率
注意:
1)對分配的數組進行delete[]刪除,不能誤用成delete刪除,若是用的是delete,那麼只會刪除數組的第1個元素內存,
後面的內存就丟失了,容易形成內存泄漏。
2)讀寫已刪除的對象。若是刪除指針後,沒有把指針置爲0,那麼就會形成野指針。
3)對同一個內存空間使用兩個delete表達式。 當第一次刪除時,對象的內存空間返還給自由存儲區,當第二次刪除時,此時自由存儲區可能會被破壞。
在編寫程序中,不免會遇到類型轉換,在C語言中用()括號來轉換,C++繼承了這種用法,可是它有一個明顯的一個缺陷
,就是不會進行類型檢測,不能保證知足轉換。在C++裏還提供了四種類型轉換:static_cast、const_cast、
dynamic_cast以及reinterpret_cast。咱們應該避免使用強制類型轉換,但若是必定要用的話,推薦使用C++裏的那四
種類型轉換,由於它們會執行類型檢測。
static_cast
可使用static_cast顯式地執行C++語言直接支持的轉換。當須要將一個較大的算術賦值給較小的類型時,如:
double d = 7.8;
int n = static_cast<int>(d);
const_cast
const_cast最爲直接,是將轉換掉表達式的const性質。彷佛從理論上講,一個變量是const,那麼就應該一直是const。
然而實際上,有時候你會發現有這種狀況,好比咱們在使用第三方的庫時候,示例:
extern void fun(char* str); //第三方的函數
void f(const char *str)
{
fun(const_cast<char*>(str));
}
dynamic_cast和reinterpret_cast
dynamic爲繼承層次結構內的類型轉換提供運行時檢測
reinterpret_cast一般爲操做數的位模式提供較低層次的從新解釋。reinterpret_cast本質上依賴於機器。爲了安全地使
用reinterpret_cast,要求程序員徹底理解所涉及的數據類型,以及編譯器實現強制類型轉換的細節
reinterpret_cast用於指針和引用轉換,不能夠對對象自己。