成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文講清C/C++ Const/Const_Cast/Constexpr

開發 后端
很多人搞不清const、const_cast、constexpr的用法,稀里糊涂地用。一般而言,即使亂用,問題也不大,因為錯大發了會崩,崩了自然會被修正,不崩自然也就沒事。

[[422168]]

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

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

一、const

C語言的const用法

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

[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指向對象的內容,另一方面只能通過p調用T類的const成員函數

  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:表示指針只能在初始化時設置指向,之后便不能修改指向。

  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] 修飾函數參數:c語言中const修飾參數反映的含義同上所述

小結: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] 修飾成員函數:表示該成員函數是只讀函數,不會修改默認參數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;需去掉函數const修飾 
  12.     }     
  13. }; 

[3] 修飾引用:引用是C++才有的語法特征,引用是別名,本質上跟指針差不多,所以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成員函數相當于承諾不會修改this的成員變量,而該承諾會被編譯器檢查,如果沒有履行承諾,則編譯器會報錯。而const Foo* f意味著不能通過f去修改f指針指向變量的內部值。

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

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

const修飾參數

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

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

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

放心大膽的調用吧,strcpy函數實現保證不會修改src的內容,編譯器會執行這種檢查。

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

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

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

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

const其他

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

二、const_cast

const_cast有什么用?

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

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

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

為什么說const_cast幾乎都反應接口設計有問題

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

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

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

const_cast或者通過c風格強轉,基本上都暴露出設計上的問題。

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

三、constexpr

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

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

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

這里我們主要講constexpr和const的區別。

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

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

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

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

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

四、結論

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

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

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

 

就醬,信不信隨你!

 

責任編輯:武曉燕 來源: 碼磚雜役
相關推薦

2011-07-20 10:06:54

CC++const

2024-03-11 15:32:50

C++開發

2010-02-02 14:06:50

C++ const變量

2025-05-09 09:25:00

2011-06-21 10:44:31

const

2011-06-21 10:37:56

const

2020-10-26 09:18:50

RedisCluste

2023-09-26 22:37:16

C++const

2024-02-23 18:04:37

C++const關鍵字

2009-08-26 17:31:59

C# const常量

2011-07-20 16:57:05

C++const

2021-01-27 09:34:51

Visual C++Dev C++codelite

2021-07-28 06:53:02

C++Const指針傳遞

2011-07-14 09:09:14

const

2009-08-27 15:17:40

C# const變量

2024-08-16 09:06:03

2024-08-06 16:28:57

2021-09-09 17:05:36

C++智能指針語言

2021-10-19 10:10:51

MySQL事務隔離級別數據庫

2009-08-27 10:54:09

C# const和st
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧洲一区视频 | 日韩免费视频一区二区 | 高清视频一区二区三区 | 人人干免费 | 亚洲精品国产精品国自产在线 | 国产欧美久久一区二区三区 | 亚洲欧美网 | 欧美亚洲国产一区二区三区 | 国产aⅴ精品 | 亚洲午夜精品一区二区三区 | 国产综合精品 | 黄色精品| 久久99精品久久久 | 午夜视频免费网站 | 亚洲第一视频网站 | 在线āv视频 | 久久久久久国产精品久久 | 亚洲精品一区二区三区蜜桃久 | 欧美mv日韩mv国产网站91进入 | 久久精品久久久久久 | 人人爱干 | 第四色影音先锋 | 亚洲精品久久久一区二区三区 | 成人h视频| 999久久久久久久久 国产欧美在线观看 | 精品国产一区二区三区日日嗨 | 国产精品久久久久久妇女6080 | 久久久久久久一区 | 成人午夜在线 | 高清欧美性猛交 | 西西裸体做爰视频 | 一级毛片免费看 | 欧美一级电影免费观看 | 在线观看国产www | 免费黄色成人 | 久久国产视频网站 | 日日想夜夜操 | 欧美日韩精品一区二区三区蜜桃 | 成人做爰9片免费看网站 | 亚洲一区二区久久久 | 国产一级在线观看 |