亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中const用法小結

2020-05-23 14:05:57
字體:
來源:轉載
供稿:網友
C++ const 允許指定一個語義約束,編譯器會強制實施這個約束,允許程序員告訴編譯器某值是保持不變的。如果在編程中確實有某個值保持不變,就應該明確使用const,這樣可以獲得編譯器的幫助。
 

const在C++中使用十分廣泛,不同位置使用的意義也不盡相同,所以想寫篇文章對其做一個總結。

首先,明確const是“不變”這個基本意義,但是不變不意味著什么都不變,下面將會看到。

1. const與變量

基本原則:const變量(對象)不能被修改

const在變量中的引入和魔數有關,所謂“魔數”指的是突然出現的一個常量值(也叫字面值常量)。

for(int i = 0; i < 512; i++){// todo}

上例中,512即為魔數,512突然出現在循環中,令人不能得知其意義,所以引入const。

const int length = 512;for(int i = 0; i < length; i++){// todo}

這樣就知道循環是在長度范圍內。

1.1 const修飾一個變量(或者說對象),使其變成一個常量,表示該變量的值無法再被修改,正因為如此,所以定義一個常量的時候,必須初始化。

1.2 const常量的作用域:

我們知道,在全局作用域內聲明一個變量(此處特指非const修飾的變量),其作用于整個程序,在其他文件中也能被引用,原因是在全局作用域聲明一個變量,默認是extern修飾的。

在全局作用域內聲明一個const變量,默認不是extern修飾,所以其只能作用于本文件內,若要在其他文件中訪問,需要顯式聲明為extern

2. const與引用

基本原則:const引用是指向const變量(對象)的引用

const int ival = 1024;const int &refVal = ival;

2.1 const引用可以指向一個相關類型(不是本類型)的const變量

double dval = 3.14;const int &refVal = dval;

編譯器將double轉換成一個臨時的int對象,然后讓const引用綁定到這個臨時對象,所以改變dval的值不會改變refVal,也就是說dval仍然是非const變量,refVal仍然是常量引用。

primer第四版是上面的說法,但我在VS2012中,const也可以指向一個本類型的非const變量,查找資料的原因大概是滿足reference-campatible條件。

理論上,我們應該嚴格遵守,常量引用指向常量對象,非常量引用指向非常量對象,避免出錯。

3. const與指針

const與指針的關系分為兩種:const修飾的指針和指向const對象的指針,二者const的位置不相同

3.1 指向const對象的指針(const位于指針符號*前面)

對于一個const對象,必須用一個指向const的指針來指向它。原因在于,const修飾使得對象無法被改變,而指針如果不是指向const的指針,則可以通過指針來修改對象,這是不被允許的。

const int ival = 1;const int *ptrVal = &ival;

反過來,對于一個指向const對象的指針,可以指向任意一個對象,這個該怎么理解呢?我們首先看看指針賦值的過程:

int *ptr = &val;

將val的地址賦值給ptr,因為賦值的只是地址,所以不知道ptr所指向的對象是否為const。

如果我們把一個地址賦值給一個指向const的指針,那么指針認為這是一個const的對象,也就是說,ptr指針指向了一個“自認為”是const的對象。

int ival = 1;const int *ptrVal = &ival;

上面的程序是正確的,我們需要明確,ival是非const變量,所以我們可以通過給ival賦值更改ival的值。ptrVal指向了一個自認為是const的對象,所以我們無法通過*ptrVal來更改ival的值。

3.2 const修飾的指針(const位于指針符號*后面)

int *const ptr;

上式聲明了一個const類型的指針,表示的意思是指針本身是一個常量,不能被修改。

如何理解?指針本身的值是一個地址,如果指針本身是一個常量,則這個地址值不能被修改,也就是說指針只能指向這個地址,不能指向其他地方。但指針所指向的地址的內容不屬于指針本身的值,所以其所指向的內容可以改變。

int ival = 1;int *const ptr = &ival;*ptr = 2;          // okint ivalTwo = 11;ptr = &ivalTwo       // error

綜上,可以定義一個指向const對象的const指針

const int *const ptr = &ival;

3.3 typedef中易出錯的const指針

typedef string *ptr;const ptr s_ptr;

上式不能直接替換理解為const string *s_prt; 從而認為s_ptr是一個指向const string的指針。
首先,ptr是一個指針,const修飾的是一個指針,所以應該是string *const s_ptr; s_ptr是一個指向string的const指針。

4. const與數組

const與數組的點在于const在定義時必須初始化這個原則,所以使用動態分配數組時,如果數組存儲的是const類型的對象,必須進行初始化(使用初始化符號())。

5. const與函數返回值

修飾函數的返回值,用于返回一個常量。

const int foo();

5.1 返回通過值傳遞

如果函數返回時采用值傳遞,比如返回一個int類型,那么函數會把返回的值(比如47)復制到外部臨時存儲單元中(產生臨時副本),所以加const修飾毫無意義

int foo();const int foo();

二者完全相同。需要注意的是,值傳遞產生臨時副本,效率低(下面const與函數參數有講),所以通常采用引用傳遞來返回。

5.2 返回通過引用傳遞(并不多見)

如果返回值不是內部類型,通常使用引用傳遞來返回結果,因為引用傳遞的是本身,不需要產生臨時副本。但需要注意的是,此時僅僅返回一個別名。

ClassType &foo();const ClassType &foo();

const修飾的返回引用值,表示函數調用的結果只能賦值給一個同類型的const引用。

5.3 返回通過指針傳遞

const ClassType *foo();

表示函數返回一個ClassType類型的指針,這個指針指向一個const對象,指針所指的內容不能被修改,所以函數的返回值只能賦值給指向一個const的同類型的指針。

const ClassType *ptr = foo();  //okClassType *ptr = foo();     //error

6. const與函數參數

首先需要明確,const修飾的目的就在于保護所修飾的內容不被改變。
在C++中,函數參數分為值傳遞,指針傳遞和引用傳遞。

6.1 值傳遞

值傳遞在函數調用時產生一個臨時副本,函數中對傳入參數的修改和操作是對副本的操作,不改變實參本身的值,所以無需const來保護。
值傳遞的保護很好,但值傳遞存在缺點,需要產生臨時副本,如果傳入的是對象,那么需要進行構造、復制、和析構等操作,效率不高。這時候可以考慮引用傳遞

void foo1(int x);void foo2(ClassType instance);     //開銷較大

下面這種保護無意義:

void foo1(const int x);void foo2(const ClassType instance);  

6.2 引用傳遞

通過傳入實參的引用,降低開銷。因為引用即本身,不需要去產生一個臨時副本。

void foo1(int &x);void foo2(ClassType &ref);

對于上述兩個函數,函數調用和值傳遞的形式完全一樣,不同的是函數內部得到的x和ref是調用傳入實參的引用。也正因為如此,引用可以通過函數改變傳入的參數來改變實參。這對與實參來說,比較危險,這時候需要通過const修飾來保護傳入的引用不被修改。

void foo1(const int &x);void foo2(const ClassType &ref);

通常來說,對于基本內部類型,不存在對象的構造等操作,所以下面兩種保護參數不被修改的方式效率基本一樣。

void foo1(int x);void foo1(const int &x);

6.3 指針傳遞

指針傳遞在保護參數不被修改上和引用傳遞是一樣的,指針傳遞還有一個功能是可以擴大接收參數的范圍:

void foo1(const ClassType *ptr);

結合上面const與指針,我們知道,ptr指向一個自認為是const類型的對象,所以!傳入的對象不一定是const修飾的對象,可以是const對象,也可以非const對象。反過來,如果沒有const修飾函數的形參,則只能傳入非const對象。

需要明確,無論傳入的是否是const對象,都無法通過指針來修改這個對象,這和上面指針與const的關系是一致的。

最后需要知道:const只能修飾一個輸入參數,如果是輸出參數,無論是引用傳遞還是指針傳遞,都不能使用const來修飾

7. const與類的數據成員

const修飾的數據成員不能在構造函數中進行初始化,只能使用成員初始化列表進行初始化。
我的理解是,因為在構造函數執行之前,使用成員初始化列表對數據成員進行初始化,如果在構造函數中對數據成員進行初始化,相當于對const進行二次賦值,這是不被允許的。

之所以這么理解,可以參照類中引用類型的初始化,也是必須在初始化列表中進行初始化,因為引用類型也是在定義的時候必須初始化,要求和const一樣,所以二者都只能使用成員初始化列表來進行初始化。

8. const與類的成員函數

const成員函數中,const位于函數的參數列表后面(函數聲明前面表示函數的返回值是一個常量)

const修飾的成員函數表示成員函數是一個只讀的作用,不改變成員變量。
const成員函數真正的含義在于,const其實修飾的成員函數的是隱含參數this指針,也就是說傳入的是const ClassType *this,因為this指向一個const對象,所以不能修改。

因為this是指向對象的指針,所以我們需要再次結合const與指針的知識:

(1)const修飾了this,得到const ClassType *this,this指向一個“自認為”是const的對象(也就是本身),所以任何對象(const或者非const)都可以調用一個const成員函數,因為傳入的指針都把自身這個對象看作是const對象,所以不能被修改。
(2)對于一個const對象,當其調用成員函數的時候,默認都傳入this指針參數,因為this此時指向一個const對象(本身),所以相當于成員函數被const修飾,成員函數是一個const成員函數,所以反過來說,const對象只能調用const成員函數,因為非const修飾的成員函數,this指針不是指向const對象。
(3)在8.2的基本上,進一步,每個成員函數都可以調用其他成員函數,每個成員函數都傳入this指針,所以成員函數相互調用必須保持this指針的一致性,所以const成員函數只能調用const成員函數,因為二者傳入的this指針都是const修飾的。對于非const成員函數,其傳入非const修飾的this指針,所以不能被調用。

搞清楚const真正的含義就明白了,一定要保持const成員函數傳入的是const指針這個意識,對象調用就需要看對象(本身,指針,引用)是否是const。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精欧美一区二区三区| 欧美成人一区在线| 永久555www成人免费| 不卡av日日日| 精品亚洲va在线va天堂资源站| 亚洲国产精品字幕| 国产不卡一区二区在线播放| 精品国产美女在线| 国产91免费观看| 久久久久这里只有精品| 亚洲国产精久久久久久| 日韩一区二区久久久| 精品国产拍在线观看| 亚洲一区久久久| 欧美一级黑人aaaaaaa做受| 日韩中文字幕在线播放| 91日韩在线播放| 国产欧美亚洲精品| 国产91色在线播放| 国产精品丝袜高跟| 亚洲精品福利资源站| 国产精品青草久久久久福利99| 亚洲成avwww人| 国产精品偷伦一区二区| 国产精品va在线播放我和闺蜜| 国产精品扒开腿爽爽爽视频| 久久久久久亚洲精品中文字幕| 日韩电影大全免费观看2023年上| 亚洲成人网在线| 久久精品久久久久久国产 免费| 九九精品在线播放| 国产一区视频在线| 日韩精品在线影院| 亚洲激情在线观看| 韩国福利视频一区| 全亚洲最色的网站在线观看| 国产va免费精品高清在线观看| 久久av红桃一区二区小说| 国产亚洲人成a一在线v站| 国产亚洲欧美aaaa| 欧美成人精品在线视频| 亚洲高清av在线| 国语自产偷拍精品视频偷| 国产精品久久久久久超碰| 国产噜噜噜噜久久久久久久久| 一本一本久久a久久精品牛牛影视| 亚洲天堂日韩电影| 91成人免费观看网站| 欧美日韩免费观看中文| 伊人一区二区三区久久精品| 日韩欧美成人区| 欧洲成人在线视频| 欧美精品videofree1080p| 最好看的2019的中文字幕视频| 亚洲国产欧美精品| 欧美刺激性大交免费视频| 欧美性感美女h网站在线观看免费| 91在线视频免费| 欧美中文在线观看| 色综合天天综合网国产成人网| 亚洲区在线播放| 疯狂蹂躏欧美一区二区精品| 欧美天天综合色影久久精品| 亚洲成人网久久久| 国产精品中文字幕在线观看| 精品电影在线观看| 黑人巨大精品欧美一区二区三区| 久久成人精品一区二区三区| 国产精品盗摄久久久| 亚洲日本欧美中文幕| 国产视频综合在线| 在线免费看av不卡| 精品动漫一区二区三区| 欧美国产极速在线| 亚洲欧洲日产国产网站| 国产精品va在线播放我和闺蜜| 精品网站999www| 国内精品视频久久| 在线播放国产一区中文字幕剧情欧美| 91久久夜色精品国产网站| 国产精品影院在线观看| 久久精品视频中文字幕| 日韩有码片在线观看| 久久99热精品这里久久精品| 97在线观看免费| 国产一区二区三区在线免费观看| 国产香蕉97碰碰久久人人| 亚洲自拍中文字幕| 97在线视频一区| 久久久免费精品| 国产精品久久久久久久久粉嫩av| 色老头一区二区三区在线观看| 免费91麻豆精品国产自产在线观看| 日韩av在线网址| 97香蕉久久夜色精品国产| 在线观看视频亚洲| 欧美一性一乱一交一视频| 5566成人精品视频免费| 精品日本美女福利在线观看| 国产欧美一区二区三区四区| 久久99久久99精品中文字幕| 国产精品电影在线观看| 欧美黑人一区二区三区| 欧美激情小视频| 成人网页在线免费观看| 国产aⅴ夜夜欢一区二区三区| 国产精品av网站| 久久九九热免费视频| 青青久久av北条麻妃海外网| 亚洲精选中文字幕| 尤物yw午夜国产精品视频| 欧美wwwwww| 亚洲日韩第一页| 亚洲精品日韩丝袜精品| 亚洲女人初尝黑人巨大| 国产精品成人国产乱一区| 国产精品第一第二| 日韩免费在线免费观看| 久久99视频免费| 欧美日韩在线观看视频小说| 日韩大片免费观看视频播放| 亚洲国产欧美一区二区三区同亚洲| 国产一区二中文字幕在线看| 欧美日韩国产中字| 国产精品爱久久久久久久| 国产在线不卡精品| 亚洲福利在线观看| 欧美夫妻性视频| 亚洲一区二区三区乱码aⅴ蜜桃女| 狠狠色噜噜狠狠狠狠97| 成人www视频在线观看| 亚洲精选在线观看| 欧美成人中文字幕| 久久91亚洲人成电影网站| 九九热视频这里只有精品| 91精品免费视频| 亚洲伊人久久综合| 亚洲精品国产免费| 国产成人综合一区二区三区| 久久久免费电影| 欧美丝袜一区二区三区| 欧美一级视频一区二区| 草民午夜欧美限制a级福利片| 深夜成人在线观看| 亚洲人成在线观看| 欧美在线精品免播放器视频| 国产综合视频在线观看| 欧美日韩在线另类| 国产综合香蕉五月婷在线| 亚洲女性裸体视频| 亚洲色图狂野欧美| 91久久久国产精品| 亚洲人成亚洲人成在线观看| 色婷婷久久av| 成人激情视频小说免费下载| 爽爽爽爽爽爽爽成人免费观看| 精品久久久在线观看| 视频一区视频二区国产精品| 精品无码久久久久久国产| 国产精品日韩av| 国产亚洲精品一区二555| 日韩电影在线观看永久视频免费网站| 国语自产精品视频在线看抢先版图片| 精品亚洲男同gayvideo网站|