auto類型推導(dǎo)與const

auto類型推導(dǎo)規(guī)則

C++11中新增了使用auto進(jìn)行自動(dòng)類型推斷的功能,從此使用容器等復(fù)雜類型時(shí)涵妥,可以簡(jiǎn)化代碼乖菱,非常方便。

但一開始使用auto時(shí)蓬网,有時(shí)候會(huì)看到這樣的代碼:

int x = 0;
const auto *y = &x;

這十分讓人迷惑,auto不是可以自動(dòng)類型推導(dǎo)嗎皮官?為什么有時(shí)使用auto還要加上const和星號(hào)讯沈,有時(shí)候又不需要?auto所代表的類型到底包不包括const冰木?

我們用代碼實(shí)驗(yàn)一下逼龟,實(shí)驗(yàn)方法是通過IDE(我用的是CLion)的debug模式匀钧,打斷點(diǎn)查看變量的類型。

這里分普通變量、引用、指針,三種情況分別討論。

  • 對(duì)于普通變量,auto的推導(dǎo)結(jié)果會(huì)忽略const修飾符。簡(jiǎn)單實(shí)驗(yàn)

    const int x = 0;
    auto y = x;       // y -> int 沒有保留const
    const auto z = x; // z -> const int 額外增加了const
    

    在調(diào)試模式下查看變量類型:


    可以看到y(tǒng)的類型是int骤素,忽略了const修飾。

  • 對(duì)于引用,auto的推導(dǎo)結(jié)果會(huì)保留const修飾符浴讯。

    const int x = 0;
    auto &y = x; // y的類型是 const int & 保留了const
    
    int a = 0;
    auto &b = a;       // b -> int &
    const auto &c = a; // c -> const int &
    

    可以看到奈籽,雖然a沒有const修飾狼忱,但可以在變量c定義時(shí)額外增加const修飾饲帅。

  • 對(duì)于指針丘逸,我們舉一個(gè)最簡(jiǎn)單的例子:

    int *a = 0;
    const int *b = 0;
    
    auto x = a; // x -> int*
    auto y = b; // y -> const int*
    

    可以看到湃鹊,b的const修飾也保留到了y上余赢。

經(jīng)過上面三種情況的討論举塔,我們得到了結(jié)論:

用auto初始化的變量,普通變量的const修飾會(huì)忽略聊替,而指針和引用的const修飾會(huì)保留当纱。

指針的const修飾

但是真的這么簡(jiǎn)單嗎晨横?我們知道手形,指針可以有兩個(gè)const修飾,例如 const int* pint *const p 代表不同的含義:

如果p的類型是 const int* 顷帖,那么無法通過p來修改q的內(nèi)容陶舞,也就是12這個(gè)值舅巷。例如: *p = 7 不合法钠右,因?yàn)闊o法給*p賦值。

而如果p的類型是 int *const 忘蟹,那么無法修改p的內(nèi)容飒房,也就是p只能指向0x01E0搁凸,不能指向其他地址。

當(dāng)然情屹,結(jié)合二者坪仇,如果p的類型是 const int *const 則圖中p和*p的內(nèi)容都不可修改。

可能一開始分不清這兩個(gè)const垃你,也很容易記混。實(shí)際上喂很,const優(yōu)先修飾其左邊相鄰的類型惜颇,如果左邊沒有類型,則修飾其右邊相鄰的類型少辣。所以 const int* 等價(jià)于 int const* (const修飾的都是int)凌摄,卻不等于 int *const (const修飾的是int*)。

const修飾誰漓帅,誰就不能修改锨亏。 const int* 中的const修飾int,代表int的值也就是q的值不能修改忙干;而 int * const 的const修飾的是 int* 器予,代表int*的值也就是p的值不能修改。

深究auto與指針的const

回到上面的auto推導(dǎo)指針類型的討論捐迫,你是否注意到乾翔,保留下來的是哪一個(gè)const?回到上面看一眼施戴,是左邊的const反浓。那么右邊的const能否保留呢?我們用下面的代碼實(shí)驗(yàn)一下:

int *a = 0;
const int *b = 0;
int *const c = 0;
const int *const d = 0;

auto m = a; // m -> int*
auto n = b; // n -> const int* 保留了左邊的const
auto p = c; // p -> int* 忽略了右邊的const
auto q = d; // q -> const int* 保留左邊赞哗,忽略右邊的const

const auto r = a; // r -> int* const 額外增加右邊的const

可以看到雷则,右邊的const是不會(huì)保留的。但定義變量r的時(shí)候肪笋,我們?cè)赼uto前增加const月劈,成了右邊的const。你可能要問了涂乌,為什么我明明在auto左邊加的const艺栈,結(jié)果沒有變成const int* ,卻跑到了右邊變成了int* const?

回顧一下前面說的湾盒,const優(yōu)先修飾左邊相鄰的類型湿右,如果沒有,則修飾其右邊相鄰類型罚勾。在 const auto r = a; 中毅人,const修飾的是auto吭狡,而auto推導(dǎo)為int,所以const修飾的是int丈莺,也就成了 int* const 划煮。

那么,又沒有辦法缔俄,把const加在左邊呢弛秋?

辦法是有的,我們可以這樣寫:

const auto * r = a; // r -> const int* 
// 等價(jià)于下面的定義:
auto const * r = a; // r -> const int* 俐载,也可以寫作 int const*

我們?cè)赼uto后面加一個(gè)星號(hào)蟹略,這樣一來,auto推導(dǎo)為int遏佣,const修飾auto挖炬,也就是修飾int,而不是修飾int状婶,就成了 const int* 了意敛。const和auto的位置換一下可以更清楚得看到,相當(dāng)于我們把 * 從auto里面拆了出來膛虫,把const放在了二者中間草姻。

只需要記住,const如果在最左邊走敌,那么它修飾的是右邊緊鄰的類型碴倾。對(duì)于 const int* ,const修飾的是int掉丽,而不包括星號(hào)跌榔。

auto推導(dǎo)與const修飾——一個(gè)原則

回到最初的問題,auto所代表的類型到底包不包括const捶障?前面分了三種情況討論僧须,其實(shí)總結(jié)下來,就是一個(gè)原則:

auto類型推導(dǎo)會(huì)在語法正確的前提下项炼,盡量少包含const担平。

對(duì)于引用,下面的語句中锭部,b的初始化是不合法的:

const int a = 0;
int &b = a; // 不合法
const int &c = a; // 合法

不能用一個(gè) int& 類型引用一個(gè)const int類型的變量暂论,因此,當(dāng)使用auto自動(dòng)推導(dǎo)時(shí)拌禾,也必須帶上const取胎;

對(duì)于指針,也是類似:

const int a = 0;
const int* const b = 0;

int* m = &a; // 不合法
int* n = b;  // 不合法
const int* p = b; // 合法,左邊的const不能丟闻蛀,右邊的可以丟

指針給指針賦值時(shí)匪傍,例如變量b包含兩個(gè)const,左邊的const必須保留觉痛,右邊的則可以忽略役衡。因此,使用auto進(jìn)行類型推導(dǎo)時(shí)薪棒,也會(huì)保留左邊的const手蝎。

最初的問題

回到最初的問題,在第一個(gè)例子中俐芯,為什么要使用 const auto *y = &x 這樣的方式來定義y的類型柑船?

這是因?yàn)閤本身不是常量,沒有const修飾泼各。只有用這種方式,才能得到一個(gè)常量指針亏拉,保證不會(huì)通過y來修改x的內(nèi)容扣蜻。相信通過上面的分析和實(shí)驗(yàn),你可以理解了及塘。

總結(jié)

這篇文章的知識(shí)點(diǎn):

  1. const修飾與它緊鄰的類型莽使,優(yōu)先修飾其左邊的類型。
  2. auto在類型自動(dòng)推導(dǎo)時(shí)笙僚,會(huì)在語法正確的前提下盡量少添加const芳肌。
  3. 使用 const auto * 的方式,我們可以初始化一個(gè)常量指針肋层。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亿笤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子栋猖,更是在濱河造成了極大的恐慌净薛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒲拉,死亡現(xiàn)場(chǎng)離奇詭異肃拜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)雌团,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門燃领,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锦援,你說我怎么就攤上這事猛蔽。” “怎么了雨涛?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵枢舶,是天一觀的道長(zhǎng)懦胞。 經(jīng)常有香客問我,道長(zhǎng)凉泄,這世上最難降的妖魔是什么躏尉? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮后众,結(jié)果婚禮上胀糜,老公的妹妹穿的比我還像新娘。我一直安慰自己蒂誉,他們只是感情好教藻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著右锨,像睡著了一般括堤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绍移,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天悄窃,我揣著相機(jī)與錄音,去河邊找鬼蹂窖。 笑死轧抗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞬测。 我是一名探鬼主播横媚,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼月趟!你這毒婦竟也來了灯蝴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤狮斗,失蹤者是張志新(化名)和其女友劉穎绽乔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碳褒,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡折砸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沙峻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睦授。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摔寨,靈堂內(nèi)的尸體忽然破棺而出去枷,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布删顶,位于F島的核電站竖螃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逗余。R本人自食惡果不足惜特咆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望录粱。 院中可真熱鬧腻格,春花似錦、人聲如沸啥繁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旗闽。三九已至酬核,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間适室,已是汗流浹背愁茁。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亭病,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓嘶居,卻偏偏與公主長(zhǎng)得像罪帖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子邮屁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • 本文根據(jù)眾多互聯(lián)網(wǎng)博客內(nèi)容整理后形成整袁,引用內(nèi)容的版權(quán)歸原始作者所有,僅限于學(xué)習(xí)研究使用佑吝,不得用于任何商業(yè)用途坐昙。 a...
    深紅的眼眸閱讀 1,838評(píng)論 0 2
  • 本文聊聊C++中的模板類型推導(dǎo)和auto。兩者其實(shí)是一樣的芋忿,前者推導(dǎo)T的類型炸客,后者推導(dǎo)auto的類型。本文初創(chuàng)于公...
    金戈大王閱讀 3,375評(píng)論 3 1
  • 在聲明變量時(shí)使用auto代替類型戈钢,C++編譯器就會(huì)自動(dòng)推導(dǎo)出變量的類型 sum被推導(dǎo)為int痹仙,使用auto聲明的變...
    dongwenbo閱讀 1,056評(píng)論 0 1
  • 從函數(shù)模板談起 函數(shù)模板的類型推導(dǎo)機(jī)制是在C++98時(shí)代就有的,auto的類型推導(dǎo)機(jī)制與其基本一致殉了,所以先理解函數(shù)...
    leon4ever閱讀 927評(píng)論 0 0
  • 心血來朝的就想翻譯一下Effective Modern C++开仰,非嚴(yán)謹(jǐn)翻譯,大伙兒湊合著看吧。記得剛接觸C++是考...
    EVANMORE閱讀 784評(píng)論 0 0