《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版本,這會產生不安全