沒有學(xué)不會的 C++:const 關(guān)鍵字

constC++ 中的關(guān)鍵字蟋座,它會在編譯期間(時機(jī)很重要),告訴編譯器這個對象是不能被修改的假勿。初學(xué)者一般會認(rèn)為 const 是個麻煩的東西这吻,因?yàn)樗3W屇愕某绦蚓幾g不通過,而去掉了 const 之后般堆,就不會有這么多「問題」了在孝,實(shí)不相瞞,其實(shí)我剛學(xué) C++ 的時候淮摔,有一段時間就處于這種狀態(tài)私沮。

但實(shí)際上,const 非常有用:

  1. 他可以保護(hù)變量和橙,防止它們被無意的修改仔燕。
  2. 它可以傳達(dá)有效的信息給讀你代碼的人:這個變量是不能被修改的,或者這個函數(shù)不會修該對象的成員魔招,等晰搀。
  3. const 關(guān)鍵字可以優(yōu)化編譯結(jié)果,讓可執(zhí)行程序更為緊湊办斑。
  4. const 修飾的變量還可以寫入 ROM 介質(zhì)外恕。

總之,我認(rèn)為合理的使用 const 可以讓你寫出來的程序更為嚴(yán)謹(jǐn)、健壯吁讨,不易出錯髓迎,乃至于更加高效。

const 與變量

const 修飾常量建丧,比較容易混淆的是:「 const 類型的常量指針」和「指針?biāo)赶虻膬?nèi)容為 const 」之間的區(qū)別:

int i = 0;
const int* p1 = &i; 
int const* p2 = &i; 

上面代碼表示指針?biāo)傅膬?nèi)容為 const排龄,你不能做 *p1 = 1; 這樣的操作,但可以 p1++;

int* const p3 = &i; 
const int* const p4 = &i; 

以上代碼中翎朱,p3const 指針橄维,你無法修改 p3,如 p3++;拴曲,但你可以執(zhí)行 *p3 = 1;争舞。最后一行中,p4 和其所指向的內(nèi)容都是 const 的澈灼。這里的規(guī)律是:如果 const* 號左邊竞川,就表示指針?biāo)傅膬?nèi)容是常量,否則指針本身是常量叁熔。

另外委乌,我們要盡可能的減少對 const 常量的強(qiáng)制轉(zhuǎn)換操作,即將 const 變量強(qiáng)制轉(zhuǎn)換為非 const 的荣回,或相反遭贸,尤其是前者,因?yàn)檫@會破壞你對常量賦予的承諾心软,可能會導(dǎo)致誤操作壕吹,從而引入隱蔽 bug

const int i = 9;
// 強(qiáng)制將常量 i 轉(zhuǎn)換為普通變量
const_cast<int&>(i) = 6;  
int j;
// 編譯失敗; 因?yàn)樵撜Z句強(qiáng)制將變量 j 轉(zhuǎn)換成了常量
static_cast<const int&>(j) = 7; 

const 與函數(shù)

const 與函數(shù)結(jié)合删铃,我們需要考慮3種情況:

  1. const 常量作為函數(shù)的參數(shù)傳入
  2. 函數(shù)返回 const 類型
  3. 聲明類的成員函數(shù)為 const

當(dāng) const 常量作為參數(shù)傳入時耳贬,該常量一定需要是引用類型,否則 const 起不到應(yīng)有的作用泳姐,例如

class Dog {
    string name_;
public:
    Dog(const string& name) { name_ = name; }
    void setName(const string name);
    void setName(string name);
};

上面兩個 setName() 函數(shù)等價效拭,因?yàn)樗鼈兌际侵祩鬟f(pass-by-copy),進(jìn)入函數(shù)的參數(shù)是一個臨時副本胖秒,既然是一個副本缎患,修改它或不修改它對外部沒有任何影響,所以這樣的聲明沒有意義阎肝。要使上面的 const 產(chǎn)生意義挤渔,應(yīng)該改為傳引用(pass-by-reference)的方式

    void setName(const string& name);
...
    Dog dog("");
    string strname = "xiao-D";
    dog.setName(strname)

此時,外部調(diào)用 setName 就不用擔(dān)心該函數(shù)會修改實(shí)參 strname 了风题。除此之外判导, setName 還可以被重載(overload)

    void setName(string& name); // 這里也只能是引用傳遞
    void setName(const string& name);

調(diào)用規(guī)則為嫉父,當(dāng)你的實(shí)參為 const 類型時,會調(diào)用 void setName(const string& name); 函數(shù)眼刃,否則調(diào)用 void setName(string& name);

和函數(shù)的參數(shù)為 const 一樣绕辖,當(dāng)函數(shù)返回 const 類型時,也需要是引用類型擂红,否則沒有意義仪际,即

    const string& getName() { return name_; }

這樣可以防止外部對 object 的內(nèi)部成員進(jìn)行修改。

最后昵骤,我們來看一下 const 類型的函數(shù)树碱,將以下函數(shù)加到 Dog 類中:

    void bark() const { cout << "dog " << name_ << " bark."; }

const 類型的函數(shù)表明該函數(shù)不會修改對象的成員,同時該函數(shù)也不可以調(diào)用非 const 函數(shù)变秦,例如如下操作都是不允許的

    void bark() const {
        name_ = "da-D"; // can't modify any member
        setName("mark"); // can't call a non-const function
    }

除此之外成榜,const 類型的函數(shù)也是可以重載的,即

    void bark() const { cout << "const dog " << name_ << " bark." << endl; }
    void bark() { cout << "non-const dog " << name_ << " bark." << endl; }

調(diào)用規(guī)則是蹦玫,當(dāng)對象是 const 類型時赎婚,調(diào)用 const 類型的函數(shù),否則調(diào)用非 const 類型的函數(shù)钳垮。

Dog d1;
d1.bark("QQ");
const Dog d2;
d2.bark("Wechat");

得到的結(jié)果為:

non-const dog QQ bark.
const dog Wechat bark.

參考:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惑淳,一起剝皮案震驚了整個濱河市额港,隨后出現(xiàn)的幾起案子饺窿,更是在濱河造成了極大的恐慌,老刑警劉巖移斩,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肚医,死亡現(xiàn)場離奇詭異,居然都是意外死亡向瓷,警方通過查閱死者的電腦和手機(jī)肠套,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猖任,“玉大人你稚,你說我怎么就攤上這事≈焯桑” “怎么了刁赖?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長长搀。 經(jīng)常有香客問我宇弛,道長,這世上最難降的妖魔是什么源请? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任枪芒,我火速辦了婚禮彻况,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舅踪。我一直安慰自己纽甘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布抽碌。 她就那樣靜靜地躺著贷腕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咬展。 梳的紋絲不亂的頭發(fā)上泽裳,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音破婆,去河邊找鬼涮总。 笑死,一個胖子當(dāng)著我的面吹牛祷舀,可吹牛的內(nèi)容都是我干的瀑梗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼裳扯,長吁一口氣:“原來是場噩夢啊……” “哼抛丽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饰豺,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤亿鲜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后冤吨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒿柳,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年漩蟆,在試婚紗的時候發(fā)現(xiàn)自己被綠了垒探。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡怠李,死狀恐怖圾叼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捺癞,我是刑警寧澤夷蚊,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站翘簇,受9級特大地震影響撬码,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜版保,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一呜笑、第九天 我趴在偏房一處隱蔽的房頂上張望夫否。 院中可真熱鬧,春花似錦叫胁、人聲如沸凰慈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽微谓。三九已至,卻和暖如春输钩,著一層夾襖步出監(jiān)牢的瞬間豺型,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工买乃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姻氨,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓剪验,卻偏偏與公主長得像肴焊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子功戚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,395評論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,105評論 1 32
  • 晚風(fēng)輕溫扶烈酒娶眷,意卷深秋味證道,弄堂設(shè)晏方知客啸臀,飯露余香浴驅(qū)寒届宠,淺彈輕唱伴燭眠,禪心初始夢還續(xù)壳咕,如醉今宵戀冬來
    深深是藍(lán)閱讀 216評論 2 7
  • 在iOS 11上運(yùn)行Scrollview向下偏移64px或者20px席揽,因?yàn)閕OS 11廢棄了automatical...
    c608閱讀 4,237評論 0 2
  • 幼年時,讀賀知章的《回鄉(xiāng)偶書》“ 少小離家老大回谓厘,鄉(xiāng)音無改鬢毛衰。兒童相見不相識寸谜,笑問客從何處來竟稳。”時熊痴,極為不解他爸。...
    九昸閱讀 212評論 0 2