文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++中const与constexpr的区别是什么

2023-06-21 21:49

关注

这篇文章主要讲解了“C++中const与constexpr的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中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.修饰类变量和成员变量

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

3.修饰成员函数

4.修饰指针

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

对于初学者来说这大概是很难理解的一个知识点,怎么区分这四个呢?记住秘诀,直接从右向左读就一招制敌了。

5.修饰引用

修饰引用和对象差不多,对象内容不可以改变。作为函数参数传参数,不存在copy开销,这是比较推荐的写法,例如:拷贝构造函数,赋值构造,STL里用于比较的函数或者仿函数,详情请参阅《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;

因为常引用不能改变,这种情况下编译器会创建一个临时变量来处理隐式转换,我们实际是对临时变量进行了常引用。

三.const转换

一般来说,从T*转换到const T*是比较简单的,且编译器支持的隐式转换,也可以显示的用模板处理,例如我们简单写一下RemoveConst模板,最后用using化名一下。但从const T*T*就麻烦一些,推荐使用const_cast。

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

这个关键字表示这是一个常量表达式,是一个编译期就可以确认的值,最常用于模板中,例如模板递归求值。

它可不只是变量,例如:

const int iSize1 = sizeof(int);const int iSize2 = GetSize();

iSize1是个常量,编译期的,但iSize2就不一定,它虽然不能改变,但要到GetSize()执行结束,才能知道具体值,这与常量一般在编译期就知道的思想不符,解决这个问题的方法就是改为:constexpr int iSize2 = GetSize(); 这样要求GetSize()一定要能在编译期就算出值,下面几个例子中GetSizeError()就会编译失败。GetFibo函数,编译期就已经递归计算出值。

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函数:

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的区别是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯