C++標(biāo)準(zhǔn)規(guī)定了每個(gè)算術(shù)類型的最小存儲(chǔ)空間倦卖,但它并不阻止編譯器使用更大的存儲(chǔ)空間杉适。事實(shí)上帖烘,對(duì)于 int 類型,幾乎所有的編譯器使用的存儲(chǔ)空間都比所要求的(16字節(jié))大茅糜。
c語言和c++的內(nèi)存管理
- c語言分四個(gè)區(qū):堆七芭,棧,全局區(qū)和常量區(qū)
- c++分五個(gè)區(qū): 堆蔑赘、棧狸驳、全局區(qū)、常量區(qū)和自由存儲(chǔ)區(qū)
c++的自由存取區(qū)類似于c語言的堆缩赛,存放的是malloc創(chuàng)建的內(nèi)存耙箍,
基本類型
字符類型
字符類型有兩種:char 和 wchar_t。char 類型保證了有足夠的空間酥馍,能夠存儲(chǔ)機(jī)器基本字符集中任何字符相應(yīng)的數(shù)值辩昆,因此,char 類型通常是單個(gè)機(jī)器字節(jié)(byte)物喷。wchar_t 類型用于擴(kuò)展字符集卤材,比如漢字和日語,這些字符集中的一些字符不能用單個(gè) char 表示峦失。
整數(shù)型
short扇丛、int 和 long 類型都表示整型值,存儲(chǔ)空間的大小不同尉辑。一般帆精, short類型為半個(gè)機(jī)器字長(zhǎng),int 類型為一個(gè)機(jī)器字長(zhǎng)隧魄,而 long 類型為一個(gè)或兩個(gè)機(jī)器字長(zhǎng)(在 32 位機(jī)器中 int 類型和 long 類型通常字長(zhǎng)是相同的)卓练。
浮點(diǎn)型
對(duì)于實(shí)際的程序來說,float 類型精度通常是不夠的——float 型只能保證 6 位有效數(shù)字购啄,而 double 型至少可以保證 10 位有效數(shù)字襟企,能滿足大多數(shù)計(jì)算的需要。
字面量
只有內(nèi)置類型存在字面值狮含,沒有類類型的字面值顽悼。因此,也沒有任何標(biāo)準(zhǔn)庫(kù)類型的字面值几迄。
整型字面值
整型字面量可以有三種進(jìn)制的表示:十進(jìn)制蔚龙、八進(jìn)制和十六進(jìn)制。以 0(零)開頭的字面值整數(shù)常量表示八進(jìn)制映胁,以 0x 或 0X 開頭的表示十六進(jìn)制木羹。
字面值整數(shù)常量的類型默認(rèn)為 int 或 long 類型。其精度類型決定于字面值——其值適合 int 就是 int 類型解孙,比 int 大的值就是 long 類型坑填。通過增加后綴,能夠強(qiáng)制將字面值整數(shù)常量轉(zhuǎn)換妆距,在數(shù)值后面加 L 或者 l(字母“l(fā)”大寫或小寫)指定常量為 long 類型穷遂。在數(shù)值后面加 U 或 u 定義 unsigned 類型。同時(shí)加 L 和 U就能夠得到 unsigned long 類型的字面值常量 娱据。
用十進(jìn)制或者科學(xué)計(jì)數(shù)法來表示浮點(diǎn)字面值常量蚪黑。使用科學(xué)計(jì)數(shù)法時(shí),指數(shù)用 E 或者 e 表示中剩。默認(rèn)的浮點(diǎn)字面值常量為 double 類型忌穿。在數(shù)值的后面加上 F 或 f 表示單精度。同樣加上 L 或者 l 表示擴(kuò)展精度. 1e-3f 表示的是0.001.
字符型字面量
在字符字面值前加 L 就能夠得到 wchar_t類型的寬字符字面值结啼。L'a'
字符串字面值
字符串字面值常量用雙引號(hào)括起來的零個(gè)或者多個(gè)字符表示掠剑。為了兼容 C 語言,C++ 中所有的字符串字面值都由編譯器自動(dòng)在末尾添加一個(gè)空字符郊愧。"A" 表示包含字母 A 和空字符兩個(gè)字符的字符串朴译。 也存在寬字符串字面值井佑,一樣在前面加“L”,如 L"a wide string literal"寬字符串字面值是一串常量寬字符眠寿,同樣以一個(gè)寬空字符結(jié)束躬翁。
兩個(gè)相鄰的僅由空格、制表符或換行符分開的字符串字面值(或?qū)捵址置嬷担┒⒐埃蛇B接成一個(gè)新字符串字面值盒发。這使得多行書寫長(zhǎng)字符串字面值變得簡(jiǎn)單:
string a = "123"
"456";
變量
變量名規(guī)則
變量名必須以字母或下劃線開頭,并且區(qū)分大小寫字母狡逢。char _宁舰;
初始化多個(gè)變量
當(dāng)一個(gè)定義中定義了兩個(gè)以上變量的時(shí)候,每個(gè)變量都可能有自己的初始化式奢浑。 對(duì)象的名字立即變成可見蛮艰,所以可以用同一個(gè)定義中前面已定義變量的值初始化后面的變量。
double salary = 9999.99, wage(salary + 0.01);
內(nèi)置類型的變量只有在全局定義時(shí)才會(huì)被自動(dòng)初始化為0雀彼, 而類的對(duì)象定義時(shí)如果沒有指定構(gòu)造函數(shù)印荔,不管是全局定義還是局部定義都會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)。
引用類型
引用(非const型)必須用與該引用同類型的對(duì)象初始化详羡。
定義多個(gè)引用
在一行中定義多個(gè)引用時(shí)仍律,每個(gè)名字簽名前都必須帶&,這一點(diǎn)與指針相似实柠,因?yàn)樗鼈兌际菑?fù)合類型
int i=1024, j=2048;
int &a=i, &b=j;
const引用
const引用是指向const對(duì)象的引用水泉,不能用非const引用指向const對(duì)象,const引用當(dāng)然也可以指向非const對(duì)象的引用窒盐。
非const引用只能綁定到與該引用同類型的對(duì)象草则。const引用則可以綁定到不同但相關(guān)類型的對(duì)象(多態(tài)或支持隱式類型轉(zhuǎn)換)或綁定到字面值常量上(這就是有限的兩個(gè)引用不同類型的例子)。
const int a = 1;
int b = 2;
int &c=a; //會(huì)報(bào)錯(cuò)
const int &d=b ; //正確
const int &e = a; //正確
const int &f = 1; // 正確
int &g = 1; // 錯(cuò)誤
auto &h=a; //正確 auto會(huì)保留底層const
auto &i=b; // 正確
auto &j=1; //錯(cuò)誤蟹漓,字面值需要指明const
const auto &k=1; //正確
對(duì)比炕横,最后兩個(gè)表達(dá)式,我們知道編譯器可以從右值的對(duì)象中推斷出底層const葡粒,卻無法從字面量中推出份殿,所以字面量必須顯式指出const auto;
當(dāng)指向不同類型的對(duì)象時(shí)嗽交,會(huì)臨時(shí)創(chuàng)建一個(gè)對(duì)象進(jìn)行類型轉(zhuǎn)換卿嘲。
指針類型
指針與引用的區(qū)別
- 指針是一個(gè)對(duì)象,所以可以有賦值夫壁、取地址等操作拾枣,所以可以有指向指針的引用。
- 不強(qiáng)制必須初始化
除了兩種例外情況外,其它所有指針的類型都要和它所指向的對(duì)象嚴(yán)格匹配
例外1. const對(duì)象的指針指向同類型的非const對(duì)象(比引用嚴(yán)格梅肤,引用可以不同類型)
例外2. 多態(tài)的場(chǎng)合
空指針
c++11建議 使用字面值常量nullptr來將一個(gè)指針初始化為空指針
int *a=nullptr;
等價(jià)于 int *a=0;
以前的程序用的NULL其實(shí)是一個(gè)預(yù)處理變量司蔬,這個(gè)變量定義在頭文件cstdlib中,
c++建議初始化所有的指針姨蝴,而常量指針在定義的時(shí)候必須初始化葱她。
class與 struct
用class和struct關(guān)鍵字定義類的唯一差別在于默認(rèn)訪問級(jí)別:默認(rèn)情況下,struct的成員為public似扔,而class的成員為private——《c++ primer》
類的定義
類的定義可以放在頭文件里面。
頭文件一般不包含定義搓谆,只包含extern 變量的聲明和函數(shù)的聲明炒辉。有三個(gè)例外:類的定義、值在編譯時(shí)就知道的const對(duì)象和inline函數(shù)——《c++ primer》
當(dāng)我們?cè)陬^文件中定義了const變量后泉手,每個(gè)包含這個(gè)頭文件的源文件都有了自己的const變量黔寇,當(dāng)該const變量是用常量表達(dá)式初始化時(shí),編譯器在編譯時(shí)會(huì)用常量表達(dá)式替換這些const變量斩萌,所以不會(huì)為每個(gè)源文件創(chuàng)建const對(duì)象的存儲(chǔ)空間缝裤。而當(dāng)是用函數(shù)返回值或其它內(nèi)容對(duì)const變量進(jìn)行初始化時(shí),編譯期間并不知道其值颊郎,所以就必須為其分配存儲(chǔ)空間憋飞,同時(shí)該const變量也不能定義在頭文件中。
類型別名
typedef和using都能定義類型別名
typedef double wages;
using wages=double;
如果某個(gè)類型別名指代的是符合類型或常量姆吭,那么把它用到聲明語句中就會(huì)產(chǎn)生意想不到的后果榛做。
char tmp='a';
typedef char * pstring;
const pstring cstr=&tmp;
*cstr='b';
cstr=nullptr;
pstring const cstr2=&tmp;
*cstr2='b';
cstr2=nullptr;
其實(shí)cstr1和cstr2是同樣類型的對(duì)象。
auto
C++ 是靜態(tài)類型(statically typed)語言内狸,在編譯時(shí)執(zhí)行類型檢查检眯。結(jié)果是程序中使用某個(gè)名字之前,必須先告知編譯器該名字的類型——《c++ primer》
auto的對(duì)象必須初始化昆淡,auto能在一條語句中锰瘸,聲明多個(gè)變量。一條聲明語句只能由一個(gè)基本數(shù)據(jù)類型昂灵。auto可以推斷出指針避凝,卻推不出引用,必須用auto &來定義一個(gè)引用眨补。
auto i = 0, *p = &i;
auto的對(duì)象的類型有時(shí)候會(huì)和初始值的類型不完全一致
auto與引用
當(dāng)用來為auto對(duì)象初始化的值是引用類型的時(shí)候恕曲,auto對(duì)象的類型是真正參與初始化的對(duì)象的值。
設(shè)置一個(gè)類型為auto的引用時(shí)渤涌,初始值終點(diǎn)頂層常量屬性仍然保留
const int a = 0;
int b = 0;
auto &b = a; // b是const int 類型的引用
auto c = a; // c是int類型
auto *d = &a, &e = b; // 編譯出出錯(cuò)佩谣,因?yàn)?amp;a是const int的地址,而b是int
auto與const
auto一般會(huì)忽略掉頂層const实蓬,同時(shí)底層const會(huì)被保留茸俭,比如當(dāng)初始值是一個(gè)指向常量的指針時(shí)吊履。
const int ci = 0, &cr = ci;
auto a = &ci; // 這時(shí)候a是const int * 類型的
auto b = cr; // b是int類型的
auto &c = ci; // c是const int & 類型的,因?yàn)槭堑讓觕onst
如果希望推斷出的auto類型是一個(gè)頂層const调鬓,則需要明確指出艇炎。
const auto f = ci;
decltype
c++11 引入了第二種類型說明符 decltype,它的作用是返回表達(dá)式返回值的類型腾窝,但是不會(huì)實(shí)際計(jì)算表達(dá)式的值缀踪。
decltype 遇到解引用操作將返回引用類型,引用類型的變量定義的時(shí)候必須初始化
int a;
int *p=&a;
decltype(*p) c=a; //注意這里必須初始化
decltype與變量虹脯,decltype((var))返回的是引用類型驴娃,decltype(var)返回的是正常類型。