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

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 淺談C++中const與constexpr的區別

淺談C++中const與constexpr的區別

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

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

一.const常量與#define比較

define只是簡單的替換,沒有類型,const可以做到防竄改與類型安全。

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

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

現在C++除了一些特定用法,推薦用const,inline,enum等替換宏——來自《Effective C++》條款02

二.const修飾

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

const int a = 10; 表示int對象a,是一個常量,不可以改變值,從編譯器生成二進制角度看,生成的a存放在.rodata段,也就是只讀(readonly)區域。不過并不絕對,有的時間統計優化等級開的高,也不取地址,可能會優化成立即數在.text段中。

2.修飾類變量和成員變量

?
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類成員m_iV是const變量,必須放到初始化列表中進行初始化,不能進行賦值。
  • 對于靜態常成員,與普通靜態成員類似,推薦放到類外.cpp中初始化。
  • aa只能調用const函數,如aa.GetValue(),不能調用非常成員函數aa.AddValueOneTime()。
  • 對于這種const對象,又想修改成員,可以在成員聲明加上mutable,這樣const對象aa也可以修改m_iChangeV,這種用法比較少。

3.修飾成員函數

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

4.修飾指針

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

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

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

5.修飾引用

修飾引用和對象差不多,對象內容不可以改變。作為函數參數傳參數,不存在copy開銷,這是比較推薦的寫法,例如:拷貝構造函數,賦值構造,STL里用于比較的函數或者仿函數,詳情請參閱《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;

因為常引用不能改變,這種情況下編譯器會創建一個臨時變量來處理隱式轉換,我們實際是對臨時變量進行了常引用。

三.const轉換

一般來說,從T*轉換到const T*是比較簡單的,且編譯器支持的隱式轉換,也可以顯示的用模板處理,例如我們簡單寫一下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

  • 簡單來說const修飾的對象本身不能改變就是頂層const,但如果是指針或者引用的對象不能改變,則稱為底層const。
  • const int cV = 10; cV是頂層const,本身不能改變
  • char const *p2; p2是底層const,p2本身值可以改變,但所指內容不可以改變
  • char* const p3; p3是頂層const,p3的本身值不可以改變
  • const char* const p4; p4既是頂層const,又是底層const
  • 注:對于上述模板RCType是無法移除p2這種底層const,如果要移除,請用const_cast<T*>移除,但這種操作可能引起Crash或者未知風險
?
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

這個關鍵字表示這是一個常量表達式,是一個編譯期就可以確認的值,最常用于模板中,例如模板遞歸求值。

它可不只是變量,例如:

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

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

?
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;

當然我們可以用模板寫GetCalc函數:

?
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的區別的詳細內容,更多關于C++  const與constexpr區別的資料請關注服務器之家其它相關文章!

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

延伸 · 閱讀

精彩推薦
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
主站蜘蛛池模板: 欧美性色欧美a在线播放 | 天天干夜夜玩 | free极度另类性欧美 | 男人j进女屁股视频在线观看 | 男人机机桶女人机机 | 热穴高校| youporn在线 | 香港日本三级亚洲三级 | 无人区大片免费播放器 | 香蕉久久一区二区三区啪啪 | 青青青国产视频 | 国语刺激对白勾搭视频在线观看 | 久久99国产综合精品AV蜜桃 | 日本视频在线免费播放 | 肉文np高h | 国产午夜精品久久久久 | 久9青青cao精品视频在线 | 逼中极品 | 欧美洲大黑香蕉在线视频 | 高h孕交| 亚洲AV无码国产精品色午夜情 | 我年轻漂亮的继坶2中字在线播放 | h肉动漫在线视频无修无遮挡 | 美女gif趴跪式抽搐动态图 | 公共场合高h短篇 | 久久电影院久久国产 | 涩涩五月天 | 日韩欧美国产免费看清风阁 | 亚洲欧美国产自拍 | 人妖欧美一区二区三区四区 | 美女一线天| 青青草原免费在线视频 | 亚洲不卡视频在线观看 | 午夜影院在线免费观看 | 国产剧情麻豆刘玥视频 | 欧美一级片免费在线观看 | 国产一精品一av一免费爽爽 | 亚洲午夜性春猛交xxxx | 国产亚洲精品一区二区在线观看 | heyzo在线观看| 国产欧美一区二区三区免费看 |