• <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>

            歸去來兮

             

            Effective C++讀書筆記之二 :盡可能使用const

            條款三:盡可能使用const(use const whenever possible)
            const允許你指定一個語義約束,而編譯器會強制實施這項約束。它允許你告訴編譯器和其他程序員某值應該保持不變。有一條約束需要注意,那就是:如果const出現在*號的左邊,那就是說被指物是常量;如果出現在星號右邊,則表示指針本身是常量;如果出現在兩邊,則被指物和指針都是常量。如果被指物是常量,則關鍵字const寫在類型的前面和類型之后,星號之前兩種所表示的語義是相同的。例如下面這兩種寫法是一樣的:
            void f1(const Widget* pw);
            void f2(Widget const * pw);
            const也可用來修飾STL中的迭代器。聲明迭代器為const就想聲明指針為const一樣(即T* const 指針),表示這個迭代器不得指向不同的東西。但它所指的東西的值是可以改變的。如果希望迭代器所指的東西不可改變(即模擬一個const T*指針),需要的是const_iterator:
            std::vector<int> vec;
            ...
            const std::vector<int>::iterator iter = vec.begin();// same as T* const
            *iter = 10;                                                        //no problem
            ++iter;                                                              //wrong!!
            std::vector<int>::const_iterator cIter = vec.begin();//same as const T*
            *iter = 10;                                                             //wrong!!
            ++iter;                                                                  //no problem

            const 最具威力(?)的用法是面對函數聲明時的應用。在一個函數聲明式內,const可以和函數返回值,各參數,函數自身(成員函數)產生關聯。
            令函數返回一個常量值,往往可以降低因客戶錯誤而造成的意外,而又不至于放棄安全性和高效性。例如,考慮有理數的operator*聲明式:
            class Rational(){...};
            const Rational operator* (const Rational & lhs, const Rational & rhs);
            也許你會說為什么返回一個const對象?原因是如果不這樣別人可能實現這樣的暴行:
            Rational a,b,c;
            ...
            (a*b)=c;
            下面,主要說明const作用于成員函數。
            許多人都忽視了這么一個事實,那就是如果兩個成員函數只是常量性不同,那么他們是可以重載的。考慮以下這個用來表示一大塊文字的class:

            class TextBlock{
            public:

            const char& operator[](std::size_t position) const
            {return text[position];}
            char& operator[](std::size_t position)
            {return text[position];}
            private:
            std::
            string text;
            }
            ;
            TextBlock的operator[]可以這么使用:
            TextBlock tb(
            "Hello");
            std::cout 
            << tb[0];  //調用non-const 

            const TextBlock ctb("Hello");
            std::cont 
            << ctb[0]; //調用const

            真是情形中const對象多用于passed by pointer-to-const或passed by reference-to-const的傳遞結果。上述的ctb太過于造作,下邊這個比較真實:
            void print (const TextBlocd& ctb)
            {
              std::cout 
            << ctb[0];
              
            }

            只用重載operator[]并對不同的版本給予不同的返回類型,就可以令const和non-const獲得不同的處理。
            此處需要注意一點,non-const operator[]的返回類型是個reference to char,不是char。如果operator[]返回的是個char,下邊的賦值就不能通過編譯:
            tb[0] = 'x'; //error c2106: ' = ' : left operand must be l-value
            那是因為,如果函數的返回類型是個內置類型,那么改動函數的返回值從來就不合法。縱使合法,C++以by value返回對象這一事實(條款20)意味著改動的其實只是tb.text[0]的一個副本,不是tb.text[0]本身,那不是我們想要的結果。
            下邊來說說在const和non-const成員函數中避免重復
            假設TextBlock(和CTextBlock)內的operator[]不單只是返回一個reference指向某字符,也執行邊界檢查、志記訪問信息、甚至可能進行數據完整性檢驗。把所有這些同時放進const和non-const operator[]中,導致這樣的一個怪物:
            class TextBlock{
            public:

            const char& operator[](std::size_t position) const
            {
                  
            //邊界檢查(bounds checking)
                  //志記數據訪問(log access data)
                  //檢驗數據完整性(verify data integrity)
            return text[position];
            }

            char& operator[](std::size_t position)
            {
                  
            //邊界檢查(bounds checking)
                  //志記數據訪問(log access data)
                  //檢驗數據完整性(verify data integrity)
            return text[position];
            }

            private:
            std::
            string text;
            }
            ;
            其中代碼的代碼重復性及伴隨的編譯時間,維護,代碼膨脹等問題真是令人頭疼啊。當然了,將邊界檢查……等所有代碼移植到另一個成員函數,并令兩個版本的operator[]調用它,是可能的,但是還是重復了一些代碼,例如函數調用,兩次return語句等。
            我們真正要做的,是實現operator[]的機能一次并使用它兩次。也就是說,你必須使一個調用另一個。這促使我們將常量性轉除(casting away constness)。
            就一般而言,casting是一個糟糕的想法,在條款27中有詳細的說明。然而代碼重復也不是什么令人愉快的經驗。本例中cosnt operator[]完全做掉了non-const版本該做的一切,唯一不同是其返回類型多了一個const資格修飾。這種情況下如果將返回值的const轉除是安全的,因為不論誰調用non-const operator[]都一定首先有個non-const對象,否則就不能夠調用non-const函數。所以令non-const operator[]調用其const兄弟是一個避免重復的安全做法:
            class TextBlock{
            public:

            const char& operator[](std::size_t position) const
            {



            return text[position];
            }

            char& operator[](std::size_t position)
            {
            const_cast
            <char&>(static_cast<const TextBlock&>
            (
            *this)[position]);
            }


            }
            ;
            這里面有兩個轉型動作,而不是一個。我們打算讓non-const operator[]調用const兄弟,但是non-const如果只是單純調用operator[],會遞歸調用自己。為了避免無窮遞歸,我們必須明確指出調用的是const operator[]。因此,這里將*this從其原始類型TextBlock&轉型為const TextBlock&。所以這里有兩次轉型:第一次用來為*this添加const,第二次則是從const operator[]的返回值中移除const。添加const的那一次轉型強迫進行了一次安全轉型,所以采用static_cast。移除const的那個動作只能由const_cast完成,沒有其他選擇。
            下面來考慮一下反向的做法:令const來調用non-const以避免重復。這個不是我們應該做的。const成員函數承諾絕對不改變其對象的邏輯狀態,non-const成員函數卻沒有這般承諾。如果在const函數內部調用了non-const函數,就是冒了這樣的風險:你曾經承諾不改動的那個對象被改動了。這就是為什么“const成員函數調用non-const成員函數”是一種錯誤行為:因為對象有可能因此而被改動。反向調用才是安全的:non-const函數本來就可以對其對象做任何動作,所以在其中調用一個const成員函數并不會帶來任何風險。

            本條目總結:

            Things to Remember

            • Declaring something const helps compilers detect usage errors. const can be applied to objects at any scope, to function parameters and return types, and to member functions as a whole.

            • Compilers enforce bitwise constness, but you should program using conceptual constness.

            • When const and non-const member functions have essentially identical implementations, code duplication can be avoided by having the non-const version call the const version.

            posted on 2008-12-09 23:00 Edmund 閱讀(270) 評論(0)  編輯 收藏 引用

            導航

            統計

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            91亚洲国产成人久久精品| 国产精品激情综合久久| 久久久亚洲裙底偷窥综合| 国产成人香蕉久久久久| 亚洲狠狠综合久久| 久久强奷乱码老熟女| 久久久久亚洲AV成人网| 久久精品综合网| 麻豆一区二区99久久久久| 久久99国产精品久久99果冻传媒| 欧美综合天天夜夜久久| 精品久久久久久久国产潘金莲 | 高清免费久久午夜精品| 日日狠狠久久偷偷色综合免费 | 久久男人Av资源网站无码软件 | 久久精品人人做人人爽电影蜜月| 精品久久一区二区三区| 久久久无码精品午夜| 久久亚洲AV成人无码电影| 久久这里只有精品视频99| 亚洲国产成人久久综合一| 久久精品夜夜夜夜夜久久| 亚洲va久久久久| 亚洲国产成人精品女人久久久| 国内精品伊人久久久久网站| 亚洲狠狠婷婷综合久久蜜芽 | 国内精品伊人久久久久AV影院| 久久久久99精品成人片牛牛影视| 久久精品a亚洲国产v高清不卡| 亚洲午夜无码久久久久小说| 无码乱码观看精品久久| 国产亚州精品女人久久久久久 | 久久久久亚洲AV综合波多野结衣| 国産精品久久久久久久| 久久久WWW成人免费毛片| 久久黄视频| 深夜久久AAAAA级毛片免费看| 伊人久久国产免费观看视频 | 99久久精品国产一区二区三区 | 久久精品国产亚洲av麻豆小说 | 国内精品伊人久久久久av一坑|