1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

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

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      C++中const以及constexpr

      一.const常量與#define比較

      • define只是簡單的替換,沒有類型,const可以做到防竄改與類型安全。
      • 而且#define會在內(nèi)存中可能(有幾次替換就有幾次拷貝)有多份拷貝,對于字面值常量加不加const都一樣,例如:const char* arr = “123”;,儲存在常量區(qū),只有一份拷貝;對于局部對象,常量存放在棧區(qū),例如:void add(){const char crr[] = “123”;},這里“123”本應(yīng)儲存在棧上,但編譯器可能會做某些優(yōu)化,將其放入常量區(qū);對于全局對象,常量存放在全局/靜態(tài)存儲區(qū);用const會比#define使用更少的空間,效率更高。
      • 這里有一個小例子:char* brr = "123"; char drr[] = "123";前者字符串123存在常量區(qū),不能通過brr去修改"123"的值;后者"123"保存在棧區(qū),可以通過drr去修改。
      • 現(xiàn)在C++除了一些特定用法,推薦用const,inline,enum等替換宏——來自《Effective C++》條款02

      二.const修飾

      1. 修飾普通變量,必須初始化
        const int a = 10; 表示int對象a,是一個常量,不可以改變值,從編譯器生成二進(jìn)制角度看,生成的a存放在.rodata段,也就是只讀(readonly)區(qū)域。不過并不絕對,有的時間統(tǒng)計優(yōu)化等級開的高,也不取地址,可能會優(yōu)化成立即數(shù)在.text段中。

      1. 修飾類變量和成員變量
      class cAAA{
      public:
          cAAA(int a) : m_iV(a){}
          const int GetValue() const {return m_iV;}
          void AddValueOneTime(){m_iChangeV++;}
      private:
          const int m_iV;
      public:
          mutable int m_iChangeV;
          static const int m_iStaticV;
      };
      static const int m_iStaticV = 1000;
      
      const cAAA aa(100);
      aa.GetValue();
      aa.m_iChangeV++;
      
      • cAAA類成員m_iV是const變量,必須放到初始化列表中進(jìn)行初始化,不能進(jìn)行賦值
      • 對于靜態(tài)常成員,與普通靜態(tài)成員類似,推薦放到類外.cpp初始化
      • aa只能調(diào)用const函數(shù),如aa.GetValue(),不能調(diào)用非常成員函數(shù)aa.AddValueOneTime()。
      • 對于這種const對象,又想修改成員,可以在成員聲明加上mutable,這樣const對象aa也可以修改m_iChangeV,這種用法比較少。

      3.修飾成員函數(shù)

      創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)祥符,10多年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575

      • 表示這個函數(shù)可以被const對象調(diào)用,也可以被普通對象調(diào)用,不會改變對象的成員,也就是說更像一種只讀不寫型的邏輯運(yùn)算,所以有些人推薦類成員函數(shù),可以都加上const。有一個小技巧,當(dāng)const和non-const成員函數(shù)有著實質(zhì)等價的實現(xiàn)時,令non-const版本調(diào)用const版本可避免代碼重復(fù);但反過來不行,const函數(shù)內(nèi)部也必須只能調(diào)用const函數(shù)—— 《Effective C++》條款03
      • 有一點要注意,編譯器強(qiáng)制實施bitwase constness,但編寫程序時應(yīng)該使用conceptual constness,解決編譯器的bitwase constness屬性就用到了上述的mutable。關(guān)于介紹bitwase constness的具體表現(xiàn)可以參考《Effective C++》條款03。

      4.修飾指針

      const char* p1;
      char const *p2;
      char* const p3;
      const char* const p4;
      

      對于初學(xué)者來說這大概是很難理解的一個知識點,怎么區(qū)分這四個呢?記住秘訣,直接從右向左讀就一招制敵了。

      • p1是一個指針,指向char字符常量,表示p1所指對象內(nèi)容不可以改,所指地址可以改。
      • p2同p1,寫法不同,兩者等價。
      • p3是一個常量,且是個指針,指向char字符,表示p3所指對象內(nèi)容可以改,所指地址不可以改。
      • p4是一個常量,且是個指針,指向char字符常量,表示p4所指對象內(nèi)容不可以改,且所指地址也不可以改。
      • 相對來說p1,p2是最常用傳參或者返回值的手段。

      5.修飾引用

      • 修飾引用和對象差不多,對象內(nèi)容不可以改變。作為函數(shù)參數(shù)傳參數(shù),不存在copy開銷,這是比較推薦的寫法,例如:拷貝構(gòu)造函數(shù),賦值構(gòu)造,STL里用于比較的函數(shù)或者仿函數(shù),詳情請參閱《Effective C++》條款20。bool Less(const cAAA& left, const cAAA& right);
      float dValue = 1.05f;
      const int& a = dValue;
      
      const int iTemp = dValue;
      const int& a = iTemp;
      
      • 因為常引用不能改變,這種情況下編譯器會創(chuàng)建一個臨時變量來處理隱式轉(zhuǎn)換,我們實際是對臨時變量進(jìn)行了常引用。

      三.const轉(zhuǎn)換

      • 一般來說,從T*轉(zhuǎn)換到const T*是比較簡單的,且編譯器支持的隱式轉(zhuǎn)換,也可以顯示的用模板處理,例如我們簡單寫一下RemoveConst模板,最后用using化名一下。但從const T*T*就麻煩一些,推薦使用const_cast。
      template 
      struct RemoveConst{
          typedef T Type;
      };
      
      template 
      struct RemoveConst{
          typedef T Type;
      };
      
      template 
      using RCType = typename RemoveConst::Type;
      

      四.頂層const與底層const

      • 簡單來說const修飾的對象本身不能改變就是頂層const,但如果是指針或者引用的對象不能改變,則稱為底層const。
      • const int cV = 10; cV是頂層const,本身不能改變
      • char const *p2; p2是底層const,p2本身值可以改變,但所指內(nèi)容不可以改變
      • char* const p3; p3是頂層const,p3的本身值不可以改變
      • const char* const p4; p4既是頂層const,又是底層const
      • 注:對于上述模板RCType是無法移除p2這種底層const,如果要移除,請用const_cast移除,但這種操作可能引起Crash或者未知風(fēng)險
      const char* pA = "sss";
      char* pB = const_cast(pA);
      auto pC = RCType(pA);
      std::cout << "type is the same: " << std::is_same::value << std::endl;
      std::cout << "pB Type Name: " << typeid(pB).name() << "pc Type Name: " << typeid(pC).name() << std::endl;
      //pB[0] = 'A';//error, Segmentation fault
      

      五.C++11新引入的constexpr

      • 這個關(guān)鍵字表示這是一個常量表達(dá)式,是一個編譯期就可以確認(rèn)的值,最常用于模板中,例如模板遞歸求值。
      • 它可不只是變量,例如:
      const int iSize1 = sizeof(int);
      const int iSize2 = GetSize();
      

      iSize1是個常量,編譯期的,但iSize2就不一定,它雖然不能改變,但要到GetSize()執(zhí)行結(jié)束,才能知道具體值,這與常量一般在編譯期就知道的思想不符,解決這個問題的方法就是改為:constexpr int iSize2 = GetSize(); 這樣要求GetSize()一定要能在編譯期就算出值,下面幾個例子中GetSizeError()就會編譯失敗。GetFibo函數(shù),編譯期就已經(jīng)遞歸計算出值。

      constexpr int GetSize(){
        return sizeof(int) + sizeof(double);
      }
      
      constexpr int GetSizeError(){
        return random();
      }
      
      constexpr int GetCalc(int N){
        return N <= 1 ? 1 : N * GetCalc(N - 1);
      }
      
      const int iSize1 = sizeof(int);
      constexpr int iSize2 = GetSize();
      //constexpr int iSize3() = GetSizeError();
      constexpr int iSize4 = GetCalc(10);
      std::cout << iSize1 << " " << iSize2 << " " << iSize4 <
      • 當(dāng)然我們可以用模板寫GetCalc函數(shù):
      template 
      struct TCalc{
        static constexpr int iValue = N * TCalc::iValue;
      };
      
      template <>
      struct TCalc<1>{
        static constexpr int iValue = 1;
      };
      std::cout << TCalc<10>::iValue << std::endl;
      

      以上內(nèi)容總結(jié)自博主rayhunter


      當(dāng)前標(biāo)題:C++中const以及constexpr
      瀏覽地址:http://ef60e0e.cn/article/dsogddi.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
        1. <ul id="0c1fb"></ul>

          <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
          <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

          吴川市| 公主岭市| 饶阳县| 荔浦县| 会昌县| 宜章县| 息烽县| 博兴县| 商丘市| 周宁县| 新津县| 张掖市| 光山县| 宁明县| 清徐县| 霍城县| 苏尼特左旗| 肥东县| 腾冲县| 甘泉县| 西平县| 英吉沙县| 郁南县| 嘉黎县| 陕西省| 曲靖市| 台南县| 寿阳县| 吕梁市| 奎屯市| 马鞍山市| 湘阴县| 东方市| 扶余县| 天全县| 花莲县| 共和县| 怀安县| 佛坪县| 罗江县| 襄城县|