• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            1、什么是const?
            ?? 常類型是指使用類型修飾符const說(shuō)明的類型,常類型的變量或?qū)ο蟮闹凳遣荒鼙桓碌摹#ó?dāng)然,我們可以偷梁換柱進(jìn)行更新:)

            2、為什么引入const?
              const 推出的初始目的,正是為了取代預(yù)編譯指令,消除它的缺點(diǎn),同時(shí)繼承它的優(yōu)點(diǎn)。

            3、cons有什么主要的作用?
            ?? (1)可以定義const常量,具有不可變性。
            ??????? 例如:
            ???????????? const int Max=100;
            ???????????? int Array[Max];???????
            ?? (2)便于進(jìn)行類型檢查,使編譯器對(duì)處理內(nèi)容有更多了解,消除了一些隱患。
            ?例如:
            ???????????? void f(const int i) { .........}
            ??????? 編譯器就會(huì)知道i是一個(gè)常量,不允許修改;
            ?? (3)可以避免意義模糊的數(shù)字出現(xiàn),同樣可以很方便地進(jìn)行參數(shù)的調(diào)整和修改。
            ??????? 同宏定義一樣,可以做到不變則已,一變都變!如(1)中,如果想修改Max的內(nèi)容,只需要:const int Max=you want;即可!
            ?? (4)可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性。
            ??????? 還是上面的例子,如果在函數(shù)體內(nèi)修改了i,編譯器就會(huì)報(bào)錯(cuò);
            ??????? 例如:
            ???????????? void f(const int i) { i=10;//error! }
            ??? (5) 為函數(shù)重載提供了一個(gè)參考。
            ???????? class A
            ???????? {
            ?????????? ......
            ?????????? void f(int i)?????? {......} file://一個(gè)函數(shù)
            ?????????? void f(int i) const {......} file://上一個(gè)函數(shù)的重載
            ??????????? ......
            ????????? };
            ???? (6) 可以節(jié)省空間,避免不必要的內(nèi)存分配。
            ???????? 例如:
            ????????????? #define PI 3.14159???????? file://常量宏
            ????????????? const doulbe? Pi=3.14159;? file://此時(shí)并未將Pi放入ROM中
            ????????????? ......
            ????????????? double i=Pi;?????????????? file://此時(shí)為Pi分配內(nèi)存,以后不再分配!
            ????????????? double I=PI;?????????????? file://編譯期間進(jìn)行宏替換,分配內(nèi)存
            ????????????? double j=Pi;?????????????? file://沒(méi)有內(nèi)存分配
            ????????????? double J=PI;?????????????? file://再進(jìn)行宏替換,又一次分配內(nèi)存!
            ???????? const定義常量從匯編的角度來(lái)看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運(yùn)行過(guò)程中只有一份拷貝,而#define定義的常量在內(nèi)存中有若干個(gè)拷貝。
            ???? (7) 提高了效率。
            ?????????? 編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒(méi)有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高。

            3、如何使用const?
            ?? (1)修飾一般常量
              ?? 一般常量是指簡(jiǎn)單類型的常量。這種常量在定義時(shí),修飾符const可以用在類型說(shuō)明符前,也可以用在類型說(shuō)明符后。
            ?????? 例如:??
            ?????????? int const x=2;  或  const int x=2;
            ?? (2)修飾常數(shù)組
              ???? 定義或說(shuō)明一個(gè)常數(shù)組可采用如下格式:
              ???? int const a[5]={1, 2, 3, 4, 5}; 
            ???????? const int a[5]={1, 2, 3, 4, 5};
            ?? (3)修飾常對(duì)象
            ????  常對(duì)象是指對(duì)象常量,定義格式如下:
            ? class A;
              ???? const A a;
            ???????? A const a;
              ??? 定義常對(duì)象時(shí),同樣要進(jìn)行初始化,并且該對(duì)象不能再被更新,修飾符const可以放在類名后面,也可以放在類名前面。 
            ?? (4)修飾常指針
            ??????? const int *A;??????? file://const修飾指向的對(duì)象,A可變,A指向的對(duì)象不可變
            ??????? int const *A;  ???? file://const修飾指向的對(duì)象,A可變,A指向的對(duì)象不可變
            ??????? int *const A;  ???? file://const修飾指針A,???? A不可變,A指向的對(duì)象可變
            ??????? const int *const A;? file://指針A和A指向的對(duì)象都不可變
            ?? (5)修飾常引用
            ??????  使用const修飾符也可以說(shuō)明引用,被說(shuō)明的引用為常引用,該引用所引用的對(duì)象不能被更新。其定義格式如下:
              ???? const double & v;
              (6)修飾函數(shù)的常參數(shù)
            ??????? const修飾符也可以修飾函數(shù)的傳遞參數(shù),格式如下:
            ??????? void Fun(const int Var);
            ??????? 告訴編譯器Var在函數(shù)體中的無(wú)法改變,從而防止了使用者的一些無(wú)意的或錯(cuò)誤的修改。????
            ?? (7)修飾函數(shù)的返回值:
            ??????? const修飾符也可以修飾函數(shù)的返回值,是返回值不可被改變,格式如下:
            ??????????? const int Fun1();
            ??????????? const MyClass Fun2();
            ?? (8)修飾類的成員函數(shù):
            ??????? const修飾符也可以修飾類的成員函數(shù),格式如下:
            ??????????? class ClassName
            ???? {
            ???????????? public:
            ???????????  ???  int Fun() const;
            ???????????  ?????? .....
            ???????????? };
            ??????? 這樣,在調(diào)用函數(shù)Fun時(shí)就不能修改類里面的數(shù)據(jù)
            ??? (9)在另一連接文件中引用const常量
            ???????? extern const int i;???? file://正確的引用
            ???????? extern const int j=10;? file://錯(cuò)誤!常量不可以被再次賦值
            ??? 另外,還要注意,常量必須初始化!
            ???????? 例如:
            ???????????? const int i=5;?

            4、幾點(diǎn)值得討論的地方:
            ?? (1)const究竟意味著什么?
            ??????? 說(shuō)了這么多,你認(rèn)為const意味著什么?一種修飾符?接口抽象?一種新類型?
            ??????? 也許都是,在Stroustup最初引入這個(gè)關(guān)鍵字時(shí),只是為對(duì)象放入ROM做出了一種可能,對(duì)于const對(duì)象,C++既允許對(duì)其進(jìn)行靜態(tài)初始化,也允許對(duì)他進(jìn)行動(dòng)態(tài)初始化。理想的const對(duì)象應(yīng)該在其構(gòu)造函數(shù)完成之前都是可寫(xiě)的,在析夠函數(shù)執(zhí)行開(kāi)始后也都是可寫(xiě)的,換句話說(shuō),const對(duì)象具有從構(gòu)造函數(shù)完成到析夠函數(shù)執(zhí)行之前的不變性,如果違反了這條規(guī)則,結(jié)果都是未定義的!雖然我們把const放入ROM中,但這并不能夠保證const的任何形式的墮落,我們后面會(huì)給出具體的辦法。無(wú)論const對(duì)象被放入ROM中,還是通過(guò)存儲(chǔ)保護(hù)機(jī)制加以保護(hù),都只能保證,對(duì)于用戶而言這個(gè)對(duì)象沒(méi)有改變。換句話說(shuō),廢料收集器(我們以后會(huì)詳細(xì)討論,這就一筆帶過(guò))或數(shù)據(jù)庫(kù)系統(tǒng)對(duì)一個(gè)const的修改怎沒(méi)有任何問(wèn)題。
            ?? (2)位元const V.S. 抽象const?
            ??????? 對(duì)于關(guān)鍵字const的解釋有好幾種方式,最常見(jiàn)的就是位元const 和 抽象const。下面我們看一個(gè)例子:
            ??????? class A
            ??????? {
            ???????? public:
            ?????????????? ......
            ?????????????? A f(const A& a);
            ?????????????? ......
            ???????? };
            ???????? 如果采用抽象const進(jìn)行解釋,那就是f函數(shù)不會(huì)去改變所引用對(duì)象的抽象值,如果采用位元const進(jìn)行解釋,那就成了f函數(shù)不會(huì)去改變所引用對(duì)象的任何位元。
            ???????? 我們可以看到位元解釋正是c++對(duì)const問(wèn)題的定義,const成員函數(shù)不被允許修改它所在對(duì)象的任何一個(gè)數(shù)據(jù)成員。
            ???????? 為什么這樣呢?因?yàn)槭褂梦辉猚onst有2個(gè)好處:
            ???????? 最大的好處是可以很容易地檢測(cè)到違反位元const規(guī)定的事件:編譯器只用去尋找有沒(méi)有對(duì)數(shù)據(jù)成員的賦值就可以了。另外,如果我們采用了位元const,那么,對(duì)于一些比較簡(jiǎn)單的const對(duì)象,我們就可以把它安全的放入ROM中,對(duì)于一些程序而言,這無(wú)疑是一個(gè)很重要的優(yōu)化方式。(關(guān)于優(yōu)化處理,我們到時(shí)候?qū)iT進(jìn)行討論)
            ???????? 當(dāng)然,位元const也有缺點(diǎn),要不然,抽象const也就沒(méi)有產(chǎn)生的必要了。
            ???????? 首先,位元const的抽象性比抽象const的級(jí)別更低!實(shí)際上,大家都知道,一個(gè)庫(kù)接口的抽象性級(jí)別越低,使用這個(gè)庫(kù)就越困難。
            ???????? 其次,使用位元const的庫(kù)接口會(huì)暴露庫(kù)的一些實(shí)現(xiàn)細(xì)節(jié),而這往往會(huì)帶來(lái)一些負(fù)面效應(yīng)。所以,在庫(kù)接口和程序?qū)崿F(xiàn)細(xì)節(jié)上,我們都應(yīng)該采用抽象const。
            ???????? 有時(shí),我們可能希望對(duì)const做出一些其它的解釋,那么,就要注意了,目前,大多數(shù)對(duì)const的解釋都是類型不安全的,這里我們就不舉例子了,你可以自己考慮一下,總之,我們盡量避免對(duì)const的重新解釋。
            ?? (3)放在類內(nèi)部的常量有什么限制?
            ??????? 看看下面這個(gè)例子:
            ??????? class A
            ??????? {
            ???????? private:
            ?????????? const int c3 = 7;?????????? // ???
            ?? ??? static int c4 = 7;????????? // ???
            ?? ??? static const float c5 = 7;? // ???
            ????????? ......
            ? };
            ???????? 你認(rèn)為上面的3句對(duì)嗎?呵呵,都不對(duì)!使用這種類內(nèi)部的初始化語(yǔ)法的時(shí)候,常量必須是被一個(gè)常量表達(dá)式初始化的整型或枚舉類型,而且必須是static和const形式。這顯然是一個(gè)很嚴(yán)重的限制!
            ???????? 那么,我們的標(biāo)準(zhǔn)委員會(huì)為什么做這樣的規(guī)定呢?一般來(lái)說(shuō),類在一個(gè)頭文件中被聲明,而頭文件被包含到許多互相調(diào)用的單元去。但是,為了避免復(fù)雜的編譯器規(guī)則,C++要求每一個(gè)對(duì)象只有一個(gè)單獨(dú)的定義。如果C++允許在類內(nèi)部定義一個(gè)和對(duì)象一樣占據(jù)內(nèi)存的實(shí)體的話,這種規(guī)則就被破壞了。
            ??? (4)如何初始化類內(nèi)部的常量?
            ???????? 一種方法就是static 和 const 并用,在內(nèi)部初始化,如上面的例子;
            ???????? 另一個(gè)很常見(jiàn)的方法就是初始化列表:
            ???????? class A
            ???????? {
            ????????? public:
            ??????????????? A(int i=0):test(i) {}
            ????????? private:
            ??????????????? const int i;
            ????????? };
            ????????? 還有一種方式就是在外部初始化,例如:
            ???????? class A
            ???????? {
            ????????? public:
            ??????????????? A() {}
            ????????? private:
            ??????????????? static const int i;? file://注意必須是靜態(tài)的!
            ????????? };
            ????????? const int A::i=3;
            ???? (5)常量與數(shù)組的組合有什么特殊嗎?
            ????????? 我們給出下面的代碼:
            ?????????? const int size[3]={10,20,50};
            ?????????? int array[size[2]];
            ?????????? 有什么問(wèn)題嗎?對(duì)了,編譯通不過(guò)!為什么呢?
            ?????????? const可以用于集合,但編譯器不能把一個(gè)集合存放在它的符號(hào)表里,所以必須分配內(nèi)存。在這種情況下,const意味著“不能改變的一塊存儲(chǔ)”。然而,其值在編譯時(shí)不能被使用,因?yàn)榫幾g器在編譯時(shí)不需要知道存儲(chǔ)的內(nèi)容。自然,作為數(shù)組的大小就不行了:)
            ???????? 你再看看下面的例子:
            ????????? class A
            ???????? {
            ????????? public:
            ??????????????? A(int i=0):test[2]({1,2}) {} file://你認(rèn)為行嗎?
            ????????? private:
            ??????????????? const int test[2];
            ????????? };
            ???????? vc6下編譯通不過(guò),為什么呢?
            ???????? 關(guān)于這個(gè)問(wèn)題,前些時(shí)間,njboy問(wèn)我是怎么回事?我反問(wèn)他:“你認(rèn)為呢?”他想了想,給出了一下解釋,大家可以看看:我們知道編譯器堆初始化列表的操作是在構(gòu)造函數(shù)之內(nèi),顯式調(diào)用可用代碼之前,初始化的次序依據(jù)數(shù)據(jù)聲明的次序。初始化時(shí)機(jī)應(yīng)該沒(méi)有什么問(wèn)題,那么就只有是編譯器對(duì)數(shù)組做了什么手腳!其實(shí)做什么手腳,我也不知道,我只好對(duì)他進(jìn)行猜測(cè):編譯器搜索到test發(fā)現(xiàn)是一個(gè)非靜態(tài)的數(shù)組,于是,為他分配內(nèi)存空間,這里需要注意了,它應(yīng)該是一下分配完,并非先分配test[0],然后利用初始化列表初始化,再分配test[1],這就導(dǎo)致數(shù)組的初始化實(shí)際上是賦值!然而,常量不允許賦值,所以無(wú)法通過(guò)。
            ??????? 呵呵,看了這一段冠冕堂皇的話,真讓我笑死了!njboy別怪我揭你短呀:)我對(duì)此的解釋是這樣的:C++標(biāo)準(zhǔn)有一個(gè)規(guī)定,不允許無(wú)序?qū)ο笤陬悆?nèi)部初始化,數(shù)組顯然是一個(gè)無(wú)序的,所以這樣的初始化是錯(cuò)誤的!對(duì)于他,只能在類的外部進(jìn)行初始化,如果想讓它通過(guò),只需要聲明為靜態(tài)的,然后初始化。
            ???????? 這里我們看到,常量與數(shù)組的組合沒(méi)有什么特殊!一切都是數(shù)組惹的禍!
            ?? (6)this指針是不是const類型的?
            ??????? this指針是一個(gè)很重要的概念,那該如何理解她呢?也許這個(gè)話題太大了,那我們縮小一些:this指針是個(gè)什么類型的?這要看具體情況:如果在非const成員函數(shù)中,this指針只是一個(gè)類類型的;如果在const成員函數(shù)中,this指針是一個(gè)const類類型的;如果在volatile成員函數(shù)中,this指針就是一個(gè)volatile類類型的。
            ?? (7)const到底是不是一個(gè)重載的參考對(duì)象?
            ??????? 先看一下下面的例子:
            ??????? class A
            ???????? {
            ?????????? ......
            ?????????? void f(int i)?????? {......} file://一個(gè)函數(shù)
            ?????????? void f(int i) const {......} file://上一個(gè)函數(shù)的重載
            ??????????? ......
            ????????? };
            ??????? 上面是重載是沒(méi)有問(wèn)題的了,那么下面的呢?
            ???????? class A
            ???????? {
            ?????????? ......
            ?????????? void f(int i)?????? {......} file://一個(gè)函數(shù)
            ?????????? void f(const int i) {......} file://?????
            ??????????? ......
            ???????? };
            ???????? 這個(gè)是錯(cuò)誤的,編譯通不過(guò)。那么是不是說(shuō)明內(nèi)部參數(shù)的const不予重載呢?再看下面的例子:
            ??????? class A
            ???????? {
            ?????????? ......
            ?????????? void f(int& )?????? {......} file://一個(gè)函數(shù)
            ?????????? void f(const int& ) {......} file://?????
            ??????????? ......
            ???????? };
            ???????? 這個(gè)程序是正確的,看來(lái)上面的結(jié)論是錯(cuò)誤的。為什么會(huì)這樣呢?這要涉及到接口的透明度問(wèn)題。按值傳遞時(shí),對(duì)用戶而言,這是透明的,用戶不知道函數(shù)對(duì)形參做了什么手腳,在這種情況下進(jìn)行重載是沒(méi)有意義的,所以規(guī)定不能重載!當(dāng)指針或引用被引入時(shí),用戶就會(huì)對(duì)函數(shù)的操作有了一定的了解,不再是透明的了,這時(shí)重載是有意義的,所以規(guī)定可以重載。
            ?? (8)什么情況下為const分配內(nèi)存?
            ??????? 以下是我想到的可能情況,當(dāng)然,有的編譯器進(jìn)行了優(yōu)化,可能不分配內(nèi)存。
            ??????? A、作為非靜態(tài)的類成員時(shí);
            ??????? B、用于集合時(shí);
            ??????? C、被取地址時(shí);
            ??????? D、在main函數(shù)體內(nèi)部通過(guò)函數(shù)來(lái)獲得值時(shí);
            ??????? E、const的 class或struct有用戶定義的構(gòu)造函數(shù)、析構(gòu)函數(shù)或基類時(shí);。
            ??????? F、當(dāng)const的長(zhǎng)度比計(jì)算機(jī)字長(zhǎng)還長(zhǎng)時(shí);
            ??????? G、參數(shù)中的const;
            ??????? H、使用了extern時(shí)。
            ??????? 不知道還有沒(méi)有其他情況,歡迎高手指點(diǎn):)???????
            ?? (9)臨時(shí)變量到底是不是常量?
            ??????? 很多情況下,編譯器必須建立臨時(shí)對(duì)象。像其他任何對(duì)象一樣,它們需要存儲(chǔ)空間而且必須被構(gòu)造和刪除。區(qū)別是我們從來(lái)看不到編譯器負(fù)責(zé)決定它們的去留以及它們存在的細(xì)節(jié)。對(duì)于C++標(biāo)準(zhǔn)草案而言:臨時(shí)對(duì)象自動(dòng)地成為常量。因?yàn)槲覀兺ǔ=佑|不到臨時(shí)對(duì)象,不能使用與之相關(guān)的信息,所以告訴臨時(shí)對(duì)象做一些改變有可能會(huì)出錯(cuò)。當(dāng)然,這與編譯器有關(guān),例如:vc6、vc7都對(duì)此作了擴(kuò)展,所以,用臨時(shí)對(duì)象做左值,編譯器并沒(méi)有報(bào)錯(cuò)。
            ?? (10)與static搭配會(huì)不會(huì)有問(wèn)題?
            ??????? 假設(shè)有一個(gè)類:
            ??????? class A
            ??????? {
            ???????? public:
            ???????????? ......
            ???????????? static void f() const { ......}
            ???????????? ......
            ???????? };
            ???????? 我們發(fā)現(xiàn)編譯器會(huì)報(bào)錯(cuò),因?yàn)樵谶@種情況下static不能夠與const共存!
            ???????? 為什么呢?因?yàn)閟tatic沒(méi)有this指針,但是const修飾this指針,所以...
            ???? (11)如何修改常量?
            ????????? 有時(shí)候我們卻不得不對(duì)類內(nèi)的數(shù)據(jù)進(jìn)行修改,但是我們的接口卻被聲明了const,那該怎么處理呢?我對(duì)這個(gè)問(wèn)題的看法如下:
            ?????????? 1)標(biāo)準(zhǔn)用法:mutable
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const { test=i; }
            ?????????????? private:
            ????????????????????? mutable int test;?? file://這里處理!
            ?????????????? };
            ?????????? 2)強(qiáng)制轉(zhuǎn)換:const_cast
            ?????????????? class A
            ?????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { const_cast <int>(test)=i; }//這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? };
            ??????????? 3)靈活的指針:int*
            ?????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { *test=i; }
            ?????????????? private:
            ????????????????????? int* test;?? file://這里處理!
            ?????????????? };
            ??????????? 4)未定義的處理
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { int *p=(int*)&test; *p=i; }//這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? };
            ??????????????? 注意,這里雖然說(shuō)可以這樣修改,但結(jié)果是未定義的,避免使用!
            ???????????? 5)內(nèi)部處理:this指針
            ????????????? class A
            ????????????? {
            ?????????????? public:
            ????????????????????? A(int i=0):test(i)??????? { }
            ????????????????????? void SetValue(int i)const
            ????????????????????? { ((A*)this)->test=i; }//這里處理!
            ?????????????? private:
            ????????????????????? int test;??
            ?????????????? };
            ???????????? 6)最另類的處理:空間布局
            ?????????????? class A
            ?????????????? {
            ??????????????? public:
            ????????????????????? A(int i=0):test(i),c('a') {? }
            ??????????????? private:
            ????????????????????? char c;
            ????????????????????? const int test;
            ??????????????? };
            ??????????????? int main()
            ??????????????? {
            ??????????????????? A a(3);
            ??????????????????? A* pa=&a;
            ??????????????????? char* p=(char*)pa;????
            ??????????????????? int*? pi=(int*)(p+4);//利用邊緣調(diào)整
            ??????????????????? *pi=5;???????????????? file://此處改變了test的值!
            ??????????????????? return 0;
            ???????????????? }
            ??????? 雖然我給出了6中方法,但是我只是想說(shuō)明如何更改,但出了第一種用法之外,另外5種用法,我們并不提倡,不要因?yàn)槲疫@么寫(xiě)了,你就這么用,否則,我真是要誤人子弟了:)
            ???? (12)最后我們來(lái)討論一下常量對(duì)象的動(dòng)態(tài)創(chuàng)建。
            ?????????? 既然編譯器可以動(dòng)態(tài)初始化常量,就自然可以動(dòng)態(tài)創(chuàng)建,例如:
            ?????????? const int* pi=new const int(10);
            ?????????? 這里要注意2點(diǎn):
            ?????????? 1)const對(duì)象必須被初始化!所以(10)是不能夠少的。
            ?????????? 2)new返回的指針必須是const類型的。
            ?????????? 那么我們可不可以動(dòng)態(tài)創(chuàng)建一個(gè)數(shù)組呢?
            ?????????? 答案是否定的,因?yàn)閚ew內(nèi)置類型的數(shù)組,不能被初始化。
            ?????????? 這里我們忽視了數(shù)組是類類型的,同樣對(duì)于類內(nèi)部數(shù)組初始化我們也做出了這樣的忽視,因?yàn)檫@涉及到數(shù)組的問(wèn)題,我們以后再討論。

            (const?討論第二篇)?

            水滴石穿C語(yǔ)言之正確使用const??

            楚云風(fēng)
            2004-9-16 14:46:00 文/
              基本解釋

              const是一個(gè)C語(yǔ)言的關(guān)鍵字,它限定一個(gè)變量不允許被改變。使用const在一定程度上可以提高程序的健壯性,另外,在觀看別人代碼的時(shí)候,清晰理解const所起的作用,對(duì)理解對(duì)方的程序也有一些幫助。  雖然這聽(tīng)起來(lái)很簡(jiǎn)單,但實(shí)際上,const的使用也是c語(yǔ)言中一個(gè)比較微妙的地方,微妙在何處呢?請(qǐng)看下面幾個(gè)問(wèn)題。

              問(wèn)題:const變量 & 常量

              為什么我象下面的例子一樣用一個(gè)const變量來(lái)初始化數(shù)組,ANSI C的編譯器會(huì)報(bào)告一個(gè)錯(cuò)誤呢?

            const int n = 5;
            int a[n];


              答案與分析:

              1)、這個(gè)問(wèn)題討論的是“常量”與“只讀變量”的區(qū)別。常量肯定是只讀的,例如5, “abc”,等,肯定是只讀的,因?yàn)槌绦蛑懈緵](méi)有地方存放它的值,當(dāng)然也就不能夠去修改它。而“只讀變量”則是在內(nèi)存中開(kāi)辟一個(gè)地方來(lái)存放它的值,只不過(guò)這個(gè)值由編譯器限定不允許被修改。C語(yǔ)言關(guān)鍵字const就是用來(lái)限定一個(gè)變量不允許被改變的修飾符(Qualifier)。上述代碼中變量n被修飾為只讀變量,可惜再怎么修飾也不是常量。而ANSI C規(guī)定數(shù)組定義時(shí)維度必須是“常量”,“只讀變量”也是不可以的。

              2)、注意:在ANSI C中,這種寫(xiě)法是錯(cuò)誤的,因?yàn)閿?shù)組的大小應(yīng)該是個(gè)常量,而const int n,n只是一個(gè)變量(常量 != 不可變的變量,但在標(biāo)準(zhǔn)C++中,這樣定義的是一個(gè)常量,這種寫(xiě)法是對(duì)的),實(shí)際上,根據(jù)編譯過(guò)程及內(nèi)存分配來(lái)看,這種用法本來(lái)就應(yīng)該是合理的,只是ANSI C對(duì)數(shù)組的規(guī)定限制了它。

              3)、那么,在ANSI C 語(yǔ)言中用什么來(lái)定義常量呢?答案是enum類型和#define宏,這兩個(gè)都可以用來(lái)定義常量。

            ?? 問(wèn)題:const變量 & const 限定的內(nèi)容

              下面的代碼編譯器會(huì)報(bào)一個(gè)錯(cuò)誤,請(qǐng)問(wèn),哪一個(gè)語(yǔ)句是錯(cuò)誤的呢?

            typedef char * pStr;
            char string[4] = "abc";
            const char *p1 = string;
            const pStr p2 = string;
            p1++;
            p2++;

              答案與分析:

              問(wèn)題出在p2++上。

              1)、const使用的基本形式: const char m;

              限定m不可變。

              2)、替換1式中的m, const char *pm;

              限定*pm不可變,當(dāng)然pm是可變的,因此問(wèn)題中p1++是對(duì)的。

              3)、替換1式char, const newType m;

              限定m不可變,問(wèn)題中的charptr就是一種新類型,因此問(wèn)題中p2不可變,p2++是錯(cuò)誤的。

              問(wèn)題:const變量 & 字符串常量

              請(qǐng)問(wèn)下面的代碼有什么問(wèn)題?

            char *p = "i'm hungry!";
            p[0]= 'I';

              答案與分析

              上面的代碼可能會(huì)造成內(nèi)存的非法寫(xiě)操作。分析如下, “i'm hungry”實(shí)質(zhì)上是字符串常量,而常量往往被編譯器放在只讀的內(nèi)存區(qū),不可寫(xiě)。p初始指向這個(gè)只讀的內(nèi)存區(qū),而p[0] = 'I'則企圖去寫(xiě)這個(gè)地方,編譯器當(dāng)然不會(huì)答應(yīng)。

              問(wèn)題:const變量 & 字符串常量2

              請(qǐng)問(wèn)char a[3] = "abc" 合法嗎?使用它有什么隱患?

              答案與分析

              在標(biāo)準(zhǔn)C中這是合法的,但是它的生存環(huán)境非常狹小;它定義一個(gè)大小為3的數(shù)組,初始化為“abc”,,注意,它沒(méi)有通常的字符串終止符'\0',因此這個(gè)數(shù)組只是看起來(lái)像C語(yǔ)言中的字符串,實(shí)質(zhì)上卻不是,因此所有對(duì)字符串進(jìn)行處理的函數(shù),比如strcpy、printf等,都不能夠被使用在這個(gè)假字符串上。

              問(wèn)題5:const & 指針

              類型聲明中const用來(lái)修飾一個(gè)常量,有如下兩種寫(xiě)法,那么,請(qǐng)問(wèn),下面分別用const限定不可變的內(nèi)容是什么?

              1)、const在前面

            const int nValue; //nValue是const
            const char *pContent; //*pContent是const, pContent可變
            const (char *) pContent;//pContent是const,*pContent可變
            char* const pContent; //pContent是const,*pContent可變
            const char* const pContent; //pContent和*pContent都是const

              2)、const在后面,與上面的聲明對(duì)等

            int const nValue; // nValue是const
            char const * pContent;// *pContent是const, pContent可變
            (char *) const pContent;//pContent是const,*pContent可變
            char* const pContent;// pContent是const,*pContent可變
            char const* const pContent;// pContent和*pContent都是const

              答案與分析:

              const和指針一起使用是C語(yǔ)言中一個(gè)很常見(jiàn)的困惑之處,在實(shí)際開(kāi)發(fā)中,特別是在看別人代碼的時(shí)候,常常會(huì)因?yàn)檫@樣而不好判斷作者的意圖,下面講一下我的判斷原則:

              沿著*號(hào)劃一條線,const和誰(shuí)在一邊,那么誰(shuí)就是const,即const限定的元素就是它。你可以根據(jù)這個(gè)規(guī)則來(lái)看上面聲明的實(shí)際意義,相信定會(huì)一目了然。

              另外,需要注意:對(duì)于const (char *) ; 因?yàn)閏har *是一個(gè)整體,相當(dāng)于一個(gè)類型(如 char),因此,這是限定指針是const。
            Posted on 2006-11-21 16:39 艾凡赫 閱讀(528) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++
            国产L精品国产亚洲区久久| 色88久久久久高潮综合影院 | 国产精品免费久久久久影院| 国产高潮国产高潮久久久| 狠色狠色狠狠色综合久久 | 国产精品久久久久久久久鸭| 久久亚洲精品中文字幕三区| 久久国产香蕉视频| 囯产极品美女高潮无套久久久| 国产精品免费看久久久| 久久久WWW免费人成精品| 波多野结衣久久一区二区| AAA级久久久精品无码片| 九九久久精品国产| 无码人妻久久久一区二区三区| 久久国产乱子精品免费女| 日本五月天婷久久网站| 日韩精品久久久久久| 人人妻久久人人澡人人爽人人精品| 国产成人精品久久一区二区三区| 久久精品免费网站网| 久久精品欧美日韩精品| 国产精品内射久久久久欢欢| 久久久久波多野结衣高潮| 成人精品一区二区久久久| 色欲久久久天天天综合网| 国内精品久久久久久久久电影网| 午夜天堂av天堂久久久| 手机看片久久高清国产日韩| 国产综合久久久久| 伊色综合久久之综合久久| 99久久综合国产精品二区| 少妇内射兰兰久久| 国产精品亚洲综合久久| 狠狠色伊人久久精品综合网| 99久久婷婷国产综合亚洲| 久久久无码精品亚洲日韩蜜臀浪潮| 久久播电影网| 亚洲天堂久久精品| 国产成人精品久久二区二区| 麻豆成人久久精品二区三区免费|