1. 程式人生 > >《Effective c++》 條款3:儘可能的使用const

《Effective c++》 條款3:儘可能的使用const

           const就是常量的意思,如果你做過題,你應該會碰過下面的物種情況,沒碰到也沒關係,看看區中有什麼區別?

char greeting []="hello";   
char *p=greeting;            //non-const pointer,non-const data
const char *p=greeting;      //non-const pointer ,const data
char *const p=greeting;      //const pointer ,non-const data
const char *const p=greeting ;   //const pointer ,const data

常量指標和指正常量有區別?我的之前的部落格裡面提到過:https://blog.csdn.net/m0_37690319/article/details/79607836,如果有興趣可以看一看,很多人說了方法const在*左邊表示被指物是常量,如果在const在*右邊表示指標是常量,指標的指向是不能改的,舉個例子:const char *p=greeting ,別指物是常量,有人會問那就是greeting是常量,那為什麼我直接greeting[0]='w';沒有出錯

char greeting []="hello";   
char *p=greeting; 
p[0]='w';        //error
greeting[0]='w'; //正確

關於const的下面兩種方式都是可以的,是一個意思,但是要注意啊,const *char,我本人也從來沒見過,同時也是一種錯誤的寫法,但是char * const 是有的。參考上面

const char *p=greeting;
char const *p=greeting;

 補充一個迭代器的知識點,迭代器是按照指標的模型建造出來的,我們如果要一個迭代器的指向不能改,但是指向的東西是能改的,或者迭代器指向的東西不能更改,

std::vector<int> vec;
const std::vector<int> ::iterator iter=vec.begin();
std::vector<int> :: const_iterator citer=vec.begin();

const 成員函式

       const成員你函式就是不允許修改改成員變數的值,const物件只能呼叫const成員函式,所以可以看看下面的類。

class TextBlock
{
public:
    const char & operator[](std::size_t position) const  //前面的額const char & 表示返回一個常量的引用,後面的const表示是const成員函式
    { return text[position]; }
    char & operator [](std::size_t position)
    { return text[position];}
pricate
    std::string text;
};

//呼叫情況,類中的建構函式省略,
TextBlock tb("hello");    
std::cout<<tb[0];                    //呼叫非const
const TextBlock ctb("world");
std::cout<<ctb[0];                    //const物件只能呼叫const成員函式


tb[0]='x';                            //注意這裡是對返回的引用改變
ctb[x]='x';                           //錯誤,不能對const 物件改變

注意一個問題:函式的返回值是內建型別,那麼改動函式的返回值是不合法的,因為他返回的是右值,char & 如果換成 char,那麼tb[0]='x'; 在這句話相當於在對char operator [](std::size_t position)這個函式的返回值進行賦值。

現在問一個問題,const成員函式就一定不更改物件的內容嗎?看看下面的例子

class TextBlock
{
public:
   char & operator[](std::size_t position) const  
    { return text[position]; }

pricate
    char * ptext;
};

const CTextBlock cctb("hello");
char *pc=&cctb[0];
*pc='j';

最終打印出來的是”jello“,有點超乎我們的想象,所以有時候const成員函式可以間接的修改內部物件的某些bit ,當然還可以使用另外的一種方法來修改,將成員物件宣告為 mutable。

再問一個問題?為什麼類的設計裡面  同一個操作符要設定const版本和非const版本?因為const物件只能呼叫const成員函式,那我們可能會碰到這樣的情況,

class TextBlock
{
public:
    cosnt char & operator [](std::size_t position) const 
    {
        ...//邊界校驗
        ...//日誌訪問
        ...//檢驗資料的完整性
        return text[position];    
    } 

    char & operator[] (std::size_t position)
    {
        ...//邊界校驗
        ...//日誌訪問
        ...//檢驗資料的完整性
        return text[position];
    }

private:
    std::string text;

};

甚至有人會問,何有什麼問題嗎?。。。。的確沒什麼問題,但是程式碼有些冗餘,你也可以回答不就賦值貼上一下嗎,不麻煩。。。。。程式碼的重複面臨著編譯的時間,程式碼維護、程式碼膨脹,那麼看看下面的方法

class TextBlock
{
public:
    cosnt 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]);
    }

private:
    std::string text;

};

將*this轉換為 const去呼叫operator[]的const版本,const版本的返回值是 const char &,然後呼叫const _cast去掉const屬性,這樣就減少了程式碼的冗餘,但是不要嘗試這個方法的反響做法,在const版本里面去呼叫非const版本,這會產生不安全