一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - C/C++ - 淺談C++中const與constexpr的區(qū)別

淺談C++中const與constexpr的區(qū)別

2022-03-07 14:21yytarget C/C++

C++11中新增加了用于指示常量表達(dá)式的constexpr關(guān)鍵字。本文將帶大家詳細(xì)了解一下const與constexpr之間的區(qū)別,需要的小伙伴們可以參考一下

一.const常量與#define比較

define只是簡(jiǎn)單的替換,沒(méi)有類(lèi)型,const可以做到防竄改與類(lèi)型安全。

而且#define會(huì)在內(nèi)存中可能(有幾次替換就有幾次拷貝)有多份拷貝,對(duì)于字面值常量加不加const都一樣,例如:const char* arr = “123”;,儲(chǔ)存在常量區(qū),只有一份拷貝;對(duì)于局部對(duì)象,常量存放在棧區(qū),例如:void add(){const char crr[] = “123”;},這里“123”本應(yīng)儲(chǔ)存在棧上,但編譯器可能會(huì)做某些優(yōu)化,將其放入常量區(qū);對(duì)于全局對(duì)象,常量存放在全局/靜態(tài)存儲(chǔ)區(qū);用const會(huì)比#define使用更少的空間,效率更高。

這里有一個(gè)小例子:char* brr = "123"; char drr[] = "123";前者字符串123存在常量區(qū),不能通過(guò)brr去修改"123"的值;后者"123"保存在棧區(qū),可以通過(guò)drr去修改。

現(xiàn)在C++除了一些特定用法,推薦用const,inline,enum等替換宏——來(lái)自《Effective C++》條款02

二.const修飾

1.修飾普通變量,必須初始化

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

2.修飾類(lèi)變量和成員變量

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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類(lèi)成員m_iV是const變量,必須放到初始化列表中進(jìn)行初始化,不能進(jìn)行賦值。
  • 對(duì)于靜態(tài)常成員,與普通靜態(tài)成員類(lèi)似,推薦放到類(lèi)外.cpp中初始化。
  • aa只能調(diào)用const函數(shù),如aa.GetValue(),不能調(diào)用非常成員函數(shù)aa.AddValueOneTime()。
  • 對(duì)于這種const對(duì)象,又想修改成員,可以在成員聲明加上mutable,這樣const對(duì)象aa也可以修改m_iChangeV,這種用法比較少。

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

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

4.修飾指針

?
1
2
3
4
const char* p1;
char const *p2;
char* const p3;
const char* const p4;

對(duì)于初學(xué)者來(lái)說(shuō)這大概是很難理解的一個(gè)知識(shí)點(diǎn),怎么區(qū)分這四個(gè)呢?記住秘訣,直接從右向左讀就一招制敵了。

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

5.修飾引用

修飾引用和對(duì)象差不多,對(duì)象內(nèi)容不可以改變。作為函數(shù)參數(shù)傳參數(shù),不存在copy開(kāi)銷(xiāo),這是比較推薦的寫(xiě)法,例如:拷貝構(gòu)造函數(shù),賦值構(gòu)造,STL里用于比較的函數(shù)或者仿函數(shù),詳情請(qǐng)參閱《Effective C++》條款20。bool Less(const cAAA& left, const cAAA& right);

?
1
2
3
4
5
float dValue = 1.05f;
const int& a = dValue;
 
const int iTemp = dValue;
const int& a = iTemp;

因?yàn)槌R貌荒芨淖儯@種情況下編譯器會(huì)創(chuàng)建一個(gè)臨時(shí)變量來(lái)處理隱式轉(zhuǎn)換,我們實(shí)際是對(duì)臨時(shí)變量進(jìn)行了常引用。

三.const轉(zhuǎn)換

一般來(lái)說(shuō),從T*轉(zhuǎn)換到const T*是比較簡(jiǎn)單的,且編譯器支持的隱式轉(zhuǎn)換,也可以顯示的用模板處理,例如我們簡(jiǎn)單寫(xiě)一下RemoveConst模板,最后用using化名一下。但從const T*T*就麻煩一些,推薦使用const_cast。

?
1
2
3
4
5
6
7
8
9
10
11
12
template <typename T>
struct RemoveConst{
    typedef T Type;
};
 
template <typename T>
struct RemoveConst<const T>{
    typedef T Type;
};
 
template <typename T>
using RCType = typename RemoveConst<T>::Type;

四.頂層const與底層const

  • 簡(jiǎn)單來(lái)說(shuō)const修飾的對(duì)象本身不能改變就是頂層const,但如果是指針或者引用的對(duì)象不能改變,則稱(chēng)為底層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
  • 注:對(duì)于上述模板RCType是無(wú)法移除p2這種底層const,如果要移除,請(qǐng)用const_cast<T*>移除,但這種操作可能引起Crash或者未知風(fēng)險(xiǎn)
?
1
2
3
4
5
6
const char* pA = "sss";
char* pB = const_cast<char*>(pA);
auto pC = RCType<decltype(pA)>(pA);
std::cout << "type is the same: " << std::is_same<decltype(pB), decltype(pC)>::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

這個(gè)關(guān)鍵字表示這是一個(gè)常量表達(dá)式,是一個(gè)編譯期就可以確認(rèn)的值,最常用于模板中,例如模板遞歸求值。

它可不只是變量,例如:

?
1
2
const int iSize1 = sizeof(int);
const int iSize2 = GetSize();

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 <<std::endl;

當(dāng)然我們可以用模板寫(xiě)GetCalc函數(shù):

?
1
2
3
4
5
6
7
8
9
10
template <int N>
struct TCalc{
  static constexpr int iValue = N * TCalc<N-1>::iValue;
};
 
template <>
struct TCalc<1>{
  static constexpr int iValue = 1;
};
std::cout << TCalc<10>::iValue << std::endl;

以上就是淺談C++中const與constexpr的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于C++  const與constexpr區(qū)別的資料請(qǐng)關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://www.cnblogs.com/forlqy/p/15611343.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 爱色成人网 | 女人扒开下面让男人桶爽视频 | 免费看视频网站 | 国产高清在线播放免费观看 | 久久国产综合精品欧美 | 91制片厂(果冻传媒)原档破解 | 国产精品免费综合一区视频 | 日本高清不卡一区久久精品 | 人禽l交免费视频观看+视频 | 国产好痛疼轻点好爽的视频 | 911福利视频| 明星ai人脸替换造梦在线播放 | 亚洲性爱区 | 亚洲无线一二三四区 | a毛片久久免费观看 | 亚洲AV无码偷拍在线观看 | 国产在线观看91精品一区 | 日韩视频在线免费观看 | 欧美3p大片在线观看完整版 | 99热这里只有精品国产在热久久 | 亚洲日本视频在线观看 | 国内精品久久久久影院男同志 | 黄a 大片a v 永久免费 | 久青草国产97香蕉在线视频 | 青青青久在线视频免费观看 | 国产99视频精品免视看9 | www.青青操| 亚洲欧美日韩国产综合专区 | 996热视频 | 校花被吃奶还摸下面 | 任我行视频在线观看国语 | 四虎影院永久网址 | 午夜福利电影网站鲁片大全 | 国产一区二区免费在线 | 亚洲社区在线 | 精品播放 | 久草在线精彩免费视频 | 精品亚洲综合久久中文字幕 | 504神宫寺奈绪大战黑人 | 欧美高清无砖专区欧美精品 | 国产精品日韩欧美一区二区三区 |