C++ 變量和復合類型

前面說了C++的基本數(shù)據(jù)類型,下面來看看在C++中如何定義變量和常量。

變量

定義和初始化

C++定義變量的方式和C語言一樣,也可以在定義的同時初始化。值得一提的是列表初始化,在原來的C++版本中可以用于初始化數(shù)組等。C++ 11標準增加了更廣泛的列表初始化,所以可以用列表初始化來初始化單個變量。

//定義變量
int a;
//定義并初始化
int b = 1;
//同時定義多個變量
int c = 5, d = 6;
//C++ 11 新特性:列表初始化
int e{3};

列表初始化有一個限制,如果要初始化的值超過了可容納的范圍,就會引發(fā)編譯錯誤,而直接賦值就可以。

//不能編譯
//short s{3.1415};
//可以編譯
short s = 3.1415;

對于函數(shù)內(nèi)部的局部變量來說,如果不初始化的話,值是未定義的。對于未初始化的局部變量進行操作可能導致無法預料的后果。對于全局變量,如果沒有給定初始值,默認值是0。

定義和聲明變量

變量定義告訴編譯器,我要創(chuàng)建一個變量,以后再用它。而變量聲明告訴編譯器,我要引用一個變量,所以你先按照這個變量的類型和名字去找它。聲明變量需要使用extern關(guān)鍵字,而且聲明的時候不能賦值。如果使用extern關(guān)鍵字并賦值,那么變量聲明就變成了變量定義,而且這只能用于全局變量的聲明和定義。如果對一個函數(shù)內(nèi)部的本地變量聲明添加初始化式,就會引發(fā)編譯錯誤。

//定義了一個全局變量
int global_count;

//聲明在另一個文件中定義的全局變量
extern int global_count;

標識符

標識符也就是變量、函數(shù)、類的名字,用于標識不同的對象。和大多數(shù)編程語言一樣,C++的標識符需要以字母或下劃線開頭,有數(shù)組、字母和下劃線組成,而且對大小寫敏感。

作用域

如果一個標識符定義在花括號外面,那么這個標識符的作用域就是全局作用域。全局作用域的變量可以在本文件的任何地方訪問,如果在其他文件中聲明這個標識符,那么還可以在其他文件中訪問。

如果一個標識符在某對花括號中定義,那么這個標識符的作用域就在這對花括號中,這就是局部作用域。局部作用域的標識符在超出這個塊后,就無法被訪問了。如果有一個全局變量,然后在某個作用域中又定義了一個同名變量,那么這個局部變量就會屏蔽對全局變量的訪問。如果希望訪問全局變量,需要使用域操作符::來指定。

//聲明在另一個文件中定義的全局變量
extern int global_count;

void declare_and_define()
{
    cout << global_count << endl;
    if (true)
    {
        int global_count = 5;
        cout << "同名局部變量覆蓋全局變量:" << global_count << endl;
        cout << "使用全局變量:" << ::global_count << endl;
    }
}

復合類型

復合類型指的是基于其他類型定義的更復雜的類型,這些復合類型也是C++語言的重點和難點。

指針

指針是C++語言從C語言中繼承的類型。每個變量在內(nèi)存中都有一個地址來存儲,指針就是這個地址。利用指針我們可以直接對變量進行修改。定義指針需要在指針名前添加星號*。如果要在一行定義多個指針,那么每一個指針前都需要星號。

//指針
int *p1, *p2;

有了指針,還需要將變量的地址賦給它,這需要使用取地址符&。注意指針和變量的類型必須匹配,將int型變量的地址賦給double *類型的指針是錯誤的。

int d1 = 5, d2 = 6;
//指針
int *p1, *p2;
p1 = &d1;
p2 = &d2;
cout << "d1=" << d1 << ",p1=" << *p1 << endl;

如果想由指針訪問其指向的對象,使用解引用符*。由于指針指向的是對象本身,所以使用解引用符修改對象會修改實際對象的值。

*p1 = 100;
cout << "d1=" << d1 << ",p1=" << *p1 << endl;

指針有兩種狀態(tài),一種是指向某個內(nèi)存空間,另一種是無效狀態(tài)。對于無效狀態(tài)的指針進行解引用會引發(fā)不可預料的后果,所以這種情況應該盡量避免。對于無效狀態(tài)的指針,最好將其清空。在老版本的C++語言中,我們需要引用cstdlib頭文件,并且使用其中預定義的NULL來清空指針,這個預定義的值實際上是0。在C++ 11標準中引入了一個新的字面量nullptr來代替NULL,所以在以后的程序中,我們最好使用nullptr

引用

引用是C++語言新增的一種類型,它和指針既有相似之處,也有不同之處。

先來看看如何定義引用。

int d1 = 5;
//d2是d1的引用
int& d2 = d1;

如果要在一行同時定義多個引用,需要在每個引用名前添加&

int &r1 = d1, &r2 = d2;

引用實際上是一個別名,一旦定義好,對引用的所有操作都相當于直接對原變量進行操作。這一點和指針很類似。

//修改引用也會修改原變量
d2 = 100;
cout << "d1=" << d1 << ",d2=" << d2 << endl;

但是需要注意一點,指針也是一個變量,所以一個指針可以多次賦值,指向不同變量的地址。而引用只能和一個變量綁定,所以引用在定義的時候必須初始化,而且一旦初始化,無法再綁定到其他變量。

復合類型總結(jié)

前面介紹了引用和指針兩種復合類型,這些復合類型還可以互相組合,生成更加復雜的類型聲明。對于指針和引用聲明,它們是和變量組合在一起的。所以下面的定義中,p是一個指針,而d是一個變量。如果希望聲明多個指針, 需要在每一個變量名前添加*號。

int *p, d;
//即使星號和類型放在一起,p仍然是指針,d仍然是變量
//int* p, d;

符合類型還可以互相組合。比如說,我們可以定義指針的指針。

int **pp = &p;

引用是一個別名,所以無法定義引用的指針。但是反過來可以定義指針的引用。

int*& r = p;

常量

常量定義

常量和變量一樣,唯一的不同點是常量一經(jīng)定義,它的值就不能夠在改變。常量定義和變量差不多,只不過需要使用const限定符修飾。由于常量一經(jīng)賦值就無法再改變,所以常量在定義的時候必須初始化。

//定義常量
const int const_count = 5;

編譯器在處理常量的時候,會直接將常量替換為其對應的值,所以編譯器需要知道常量的值。默認情況下,常量定義只在本文件中有效。如果在多個文件中定義了同名的常量,那么這些常量是各不相同的常量。如果需要在文件之間共享常量,就需要在常量定義和聲明上都添加extern關(guān)鍵字。

變量的const引用

我們可以把引用標記為const的,這種情況下這個引用變?yōu)橹蛔x的,我們可以修改原變量,可以通過引用讀取原變量,但是無法通過引用修改原變量。

//引用常量
int i = 5;
const int& r = i;
i = 10;
//r = 10;

指針常量

指針存儲的就是對象的地址,如果我們把指針本身定義為const的,那么我們將無法將這個指針指向其他對象的地址,但是我們可以通過這個指針修改指向?qū)ο蟮闹?/strong>。需要注意,這種定義必須將const關(guān)鍵字置于緊挨的變量名的位置。

int j = 100;
//const指針
int *const cp = &i;
//可以修改指針指向的對象的值
*cp = 10;
//無法修改指針指向的對象
//cp = &j;

指向常量的指針

這種情況和上面那種情況正好相反,這次是將指針指向的對象聲明為const的,這樣一來,我們無法修改指針指向的對象的值,但是我們可以修改指針指向其他對象的地址。這種定義需要將const放到符合聲明的最前面。雖然這種情況叫做指向常量的指針,但是這是對指針類型的聲明,實際上這個指針完全可以指向一個變量,只不過我們無法通過指針修改這個變量的值。

const int *p = &i;
//可以修改指針指向其他對象
p = &j;
//無法通過指針修改值
//*p = 200;

頂層const和底層const

前面我們看到了,指針是一個非常復雜的話題。指針本身是一個對象,而它又指向另一個對象。這些情況和常量常量聲明組合在一起,將會變得非常復雜。所以我們需要對其做出分類。我們把本身是const的對象叫做頂層const,而指向的對象是const的就叫做底層const。這樣一來就比較清楚了,指向常量的指針就是底層const,而指針常量就是頂層const。

下面這種情況,變量ccp即使頂層const又是底層const。

//既是頂層const又是底層const
const int*const ccp = &i;

constexpr和常量表達式

有時候編譯器要求程序中的某些值不能改變,而且必須在編譯期就能計算出來,這樣的值叫做常量表達式。顯然,字面量和用常量表達式初始化的const對象都是常量表達式。

當然,一個變量并不是常量表達式,哪怕我們在程序中沒有修改過變量的值也不行。一個用變量初始化的const對象也不是常量表達式。

C++ 11標準新規(guī)定了一個關(guān)鍵字constexpr,它可以讓編譯器檢查聲明的常量。如果這個常量不是合法的常量表達式,那么就無法編譯。

//常量表達式
constexpr int MAX_COUNT = 100;
constexpr int MIN_COUNT = -MAX_COUNT;
//i不是常量,所以下面的代碼不能編譯
//constexpr int VARIABLE_COUNT = i;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內(nèi)容