拨开const与constexpr迷雾

constexpr是C++11的内容,提出它的目的主要是为了解决const双重语义的问题。

"双重语义"是指”常量“与”只读“。

要搞清楚const与constexpr的关系,首先应该从”常量“与”只读“的区别入手。

”只读“:侧重对变量或对象本身的属性或者权力。即某个变量没有权利(通过自身)更改其内存。如下:

int b = 10;

const int a = b;

上面这条语句告诉我们,不可通过a变量来修改a中的内容,即不能完成如下

值得一提的是,这只是强调不可通过a来修改其内存,即不能继续以下操作:

a = 20;//a为只读,不可修改

但是却可以通过其他办法来改变其内存,很简单,使用指针修改即可:

int* pa = (int*)&a;

*pa = 30;//a的值就被修改成了30.

需要强调的是,C++中通过引用或指针修改const的值,只适用于赋的值为左值(变量)的情况!(即const int a = b;) 当被赋的值为右值(即字面量)时(const int a = 10;)便不可被修改

至于为什么,请看下文。

”常量“:侧重内存本身是常量,任何方式都无法修改此部分内存,如下:

constexpr int a = 10;

//a此时就与一个常量绑定了,在编译期间,a就会被10替换(类似于宏替换),以达到优化

注意:使用constexpr时,= 右边必须是右值(即字面常量),而不可为变量!

为了区分这两者,C++将“常量”交给了constexpr,将“只读”交给了const

还需要注意的是,C++与C不同,后者访问const 变量的值是通过其内存获取的,而前者是通过常量折叠(指const变量(即常量)值放在编译器的符号表中,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化来获取其值的。所以当如下定义时,const与constexpr效果完全相同:

const int a = 10;//与下等价:

constexpr int a = 10;//这两种情况,a的值无论如何也无法改变

值得一提的是,下面两种情况是不等价的:

int b = 10;

const int a = b;//第一种

const int a = 10//第二种

第一种情况虽然在语义上和第二种相同,但编译器对二者的处理是不一样的。前者是运行期常量,后者是编译期常量。可参考此链接

运行期常量不会进行常量折叠,编译器常量才会进行。为什么?因为运行期常量需要等到代码运行时才能确定,我们完全可以写出如下代码:

很显然,a的值需要等到我们输入k后才能确定。

此时,a就不可进行常量折叠了(因为常量折叠是在编译期进行的,而这时我们还没输入k),而是通过C语言的方式,在内存的常量区域开辟空间存放常量a的值,且此后获取a的值都需要访问其内存,而不是直接从符号表中获取。下面用一个最简单的例子进行对比:

//没有问题

//报错。 

需要补充说明的是,C++中的volatile关键字可以修饰const变量,使第二种情况下定义的const变量不从符号表中读取,则此时与第一种情况相同
(volatile具体如何使用不太清楚,此例仅供参考)

constexpr还有其他诸多特性,如常量表达式函数等,本文只浅谈constexpr与const的关系,其他内容就不详细展开了。

希望本文能够帮助到大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值