日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一文講清C/C++ Const/Const_Cast/Constexpr

本文轉(zhuǎn)載自微信公眾號「碼磚雜役」,作者我不想種地 。轉(zhuǎn)載本文請聯(lián)系碼磚雜役公眾號。

成都創(chuàng)新互聯(lián)公司是一家專注于做網(wǎng)站、成都網(wǎng)站制作與策劃設(shè)計,溫州網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:溫州等地區(qū)。溫州做網(wǎng)站價格咨詢:13518219792

很多人搞不清const、const_cast、constexpr的用法,稀里糊涂地用。一般而言,即使亂用,問題也不大,因為錯大發(fā)了會崩,崩了自然會被修正,不崩自然也就沒事。但作為一個有追求的專業(yè)程序員,自當聞過則喜,搞清楚弄明白。

一、const

C語言的const用法

先講const,這玩意兒怎么翻譯我也拿不準,C語言中該關(guān)鍵字的用法比較簡單,大概有如下幾種用法:

[1] 修飾普通變量:變量只讀,在程序運行過程中不可修改。

 
 
 
  1. const int i = 100; //i is read only 
  2. i = 200; //compile error, variable i can not assignable 

[2] 修飾指針 const T* p:表示不能通過p去修改p指向?qū)ο蟮膬?nèi)容,另一方面只能通過p調(diào)用T類的const成員函數(shù)

 
 
 
  1. const struct Foo *f = new Foo;  
  2. f->dataX = 100; //compile error 
  3.  
  4. const char* p = "abc";  
  5. p[1] = 'x'; //compile error 
  6. f->nonconst_member_function(); ///compile error (后面再講) 

[3] 修飾指針 T* const p:表示指針只能在初始化時設(shè)置指向,之后便不能修改指向。

 
 
 
  1. char s1[] = "abc";  
  2. char s2[] = "xyz"; 
  3. char* const p = s1; 
  4. p = s2; //compile error 

[4] 修飾指針 const T* const p:表示既不能通過p修改它指向的對象,又不能更改p的指向。

 
 
 
  1. const char* const p = "abc"; 
  2. p[1] = 'B'; //compile error 
  3. p = "xyz"; //compile error 

[5] 修飾函數(shù)參數(shù):c語言中const修飾參數(shù)反映的含義同上所述

小結(jié):C語言中,const的用法差不多就這些,比較簡單。

C++擴充了const的用法

[1] 修飾成員變量:const成員變量只能在初始化列表里做初始化,程序運行中不可修改;如果是const整型,則可以C++11標準之后直接初始化。

 
 
 
  1. struct Foo  
  2.     Foo() : PI(3.15) {} // PI is initialized by initializer list 
  3.     const int c = 100; //C++11 support 
  4.     const float PI; 
  5. }; 

[2] 修飾成員函數(shù):表示該成員函數(shù)是只讀函數(shù),不會修改默認參數(shù)this的成員變量,如果修改會編譯報錯。

 
 
 
  1. class Foo 
  2.     int m_money; 
  3. public: 
  4.     int get_money() const // 
  5.     { 
  6.         return m_money; 
  7.     } 
  8.  
  9.     int set_money(int money) const // 
  10.     { 
  11.         m_money = money; //修改了this->m_money;需去掉函數(shù)const修飾 
  12.     }     
  13. }; 

[3] 修飾引用:引用是C++才有的語法特征,引用是別名,本質(zhì)上跟指針差不多,所以const修飾引用跟修飾指針的語義和約束差不多。

 
 
 
  1. Foo f; 
  2. const Foo& r = f; 
  3. r.m_data = 1; //compile error 

[4] C++中對const修飾指針的補充

 
 
 
  1. struct Foo  
  2.   int const_member_function() const { return m_data; } 
  3.   int non_const_member_function(int data) { m_data = data; } 
  4.   int m_data; 
  5. }; 
  6.  
  7. int main() 
  8.   const Foo* f = new Foo; 
  9.   f->const_member_function();  //OK 
  10.   f->non_const_member_function(); //compile ERROR 
  11.   return 0; 

為什么呢?因為const成員函數(shù)相當于承諾不會修改this的成員變量,而該承諾會被編譯器檢查,如果沒有履行承諾,則編譯器會報錯。而const Foo* f意味著不能通過f去修改f指針指向變量的內(nèi)部值。

通過f->data = 1的方式肯定是不行。

另一方面,你只能通過f去調(diào)用它的const成員函數(shù),因為const成員函數(shù)的語義就是不會修改this的值,編譯器很容易執(zhí)行這個校驗。

const修飾參數(shù)

const可以修飾普通參數(shù),也可以修飾指針/引用參數(shù),因為形參是實參的副本,所以const修飾普通參數(shù)其實沒什么意義,我們著重講講const修飾指針/引用參數(shù)。

比如標準C庫函數(shù)strcpy的簽名:char *strcpy(char * dst, const char * src);

dst表示目標地址,src表示源串,const修飾了源串,這是因為從源串拷貝到目標串,不需要修改源串內(nèi)容,這相當于向strcpy調(diào)用者承諾:

放心大膽的調(diào)用吧,strcpy函數(shù)實現(xiàn)保證不會修改src的內(nèi)容,編譯器會執(zhí)行這種檢查。

這樣,在review代碼的時候,如果想追蹤src在哪里被修改了,當看到strcpy的簽名,就不用打開函數(shù)去看實現(xiàn),只要不違背承諾,肯定不是這個函數(shù)內(nèi)改動了src。

const char *src是一種承諾,也是一種約束。調(diào)用的地方,const char*形式的形參,既傳const char*實參,也可以傳char*實參,因為參數(shù)const char*是更強的承諾。

但反之不成立。比如第一個參數(shù)dst是不帶const的,那么如果有一個變量類型為const char* p,那不能把p作為第一個參數(shù)傳遞進strcpy,編譯不過。

因為strcpy不承諾不修改dst,是一個更弱的承諾,只有聲明為const指針的參數(shù),才能傳遞const指針實參。

const其他

const還可以修飾返回值,還可以跟extern結(jié)合,但這些都是一些小語法技巧,一般開發(fā)用不太到,真碰到再查不遲。

二、const_cast

const_cast有什么用?

const是C++的一個強制轉(zhuǎn)換,它用來去掉const屬性,比如:

 
 
 
  1. Foo foo; 
  2. const Foo *f1 = &foo; 
  3. Foo* f2 = const_cast(f); 
  4. Foo* f3 = (Foo*)f; 

const_cast的作用跟強轉(zhuǎn)差不多,C++加const_cast主要是為了功能完整性,const_cast作用于引用跟作用于指針差不多。

為什么說const_cast幾乎都反應(yīng)接口設(shè)計有問題

程序設(shè)計要言行一致,遵守承諾,這意味著:不應(yīng)該把參數(shù)聲明為const指針,而函數(shù)實現(xiàn)里借助強制去掉const屬性。

首先,這樣做是危險的,比如const char* p = "abc"; p指向常量字符串被作為參數(shù)傳遞,被強轉(zhuǎn)+修改,則會導(dǎo)致程序crash。

其次,這樣做是分裂的,因為你加const修飾相當于讓編譯器幫你執(zhí)行檢查,以便在你違背承諾的時候通過編譯期檢查報錯提醒你,但在它真正向你報錯的時候,你又說別管啦,老子就是要蠻干。

const_cast或者通過c風格強轉(zhuǎn),基本上都暴露出設(shè)計上的問題。

設(shè)計良好的程序基本上不需要const強轉(zhuǎn)。因為const約束在調(diào)用鏈會傳播,所以,你需要一以貫之的遵守約定,找到導(dǎo)致需要const強轉(zhuǎn)的錯誤源頭,這可能會多費一點時間,但它是值得的。

三、constexpr

const沒有區(qū)分編譯期常量和運行期常量,constexpr是C++11開始提出的關(guān)鍵字,被限定為編譯器常量,其意義與14版本有一些區(qū)別。

C++11中的constexpr指定的函數(shù)返回值和參數(shù)必須要保證是字面值,而且必須有且只有一行return代碼,這給函數(shù)的設(shè)計者帶來了更多的限制,比如通常只能通過return 三目運算符+遞歸來計算返回的字面值。

而C++14中只要保證返回值和參數(shù)是字面值就行了,函數(shù)體中可以加入更多的語句,方便了更靈活的計算。

這里我們主要講constexpr和const的區(qū)別。

constexpr可以用來修飾變量、函數(shù)、構(gòu)造函數(shù)。一旦以上任何元素被constexpr修飾,那么等于說是告訴編譯器 “請大膽地將我看成編譯時就能得出常量值的表達式去優(yōu)化我”。

 
 
 
  1. constexpr func()  
  2.   return 10; 
  3.  
  4. int main() 
  5.   int arr[func()]; 

編譯期大膽地將func()做了優(yōu)化,在編譯期就確定了func計算出的值10而無需等到運行時再去計算。

這就是constexpr的第一個作用:給編譯器足夠的信心在編譯期去做被constexpr修飾的表達式的優(yōu)化。

constexpr還有另外一個特性,雖然它本身的作用之一就是希望程序員能給編譯器做優(yōu)化的信心,但它卻猜到了自己可能會被程序員欺騙,而編譯器并不會對此“惱羞成怒”中止編譯。

四、結(jié)論

C/C++程序應(yīng)該積極的使用const/constexpr,什么叫積極使用?只要有可能,那么我們就應(yīng)該用const/constexpr。

只要可能就應(yīng)該用xx,這種話一般而言都是錯的,但用在const/constexpr卻很正確,因為使用const/constexpr基本上都會讓你的程序更健壯、更快,const修飾的整型變量,在gcc開優(yōu)化選項的時候,有可能被直接編譯到匯編代碼指令,而非生成一個變量,而constexpr的優(yōu)化作用在前面一節(jié)已經(jīng)闡述。

與之對應(yīng)的是:只要有可能,就不要使用const_cast,它基本上都反映了接口設(shè)計上的問題。

就醬,信不信隨你!


網(wǎng)站標題:一文講清C/C++ Const/Const_Cast/Constexpr
鏈接URL:http://www.dlmjj.cn/article/djdjpsd.html