深入理解C++中的const与constexpr

        导读:C++11引入了constexpr对const的补充,因此凡是表示“只读”建议用const,凡是表示“常量表达式”建议使用constexpr。

目录

 一、关于const

1、const的功能

2、辨别“只读”与“常量表达式”

二、关于constexpr

1、从本质了解constexpr

2、constexpr修饰函数


 一、关于const

1、const的功能

        在 C++11 之前只有 const 关键字,从功能上来说这个关键字有双重语义:变量只读与常量表达式,举一个简单的例子: 

void func(const int num)
{
	const int count = 24;
	int array[num];            // error,num是一个只读变量,不是常量
	int array1[count];         // ok,count是一个常量

	int a1 = 520;
	int a2 = 250;
	const int& b = a1;
	b = a2;                         // error
	a1 = 1314;
	cout << "b: " << b << endl;     // 输出结果为1314
}

        当 const 修饰的变量是只读变量时,仅仅是说明不能通过这个只读变量修改内存的值,但是可以通过其他方法修改内存值。 如下:

void func1(const int num)
{
	int a = 10;
	const int& con_b = a;
	cout << con_b << endl;//输出为10
	a = 20;
	cout << con_b << endl;//输出20,改变了con_b的值大小
}

 2、辨别“只读”与“常量表达式”

        看了前面的关于 const 的内容,不知道是不是有疑问,const 什么时候为只读变量,什么时候是常量?

       (1) 编译期间能直接确定初始值的 const 标示符,都被作为常量表达式处理。

       (2)在运行期间才能确定其初始值的按照只读变量处理。

       我们来看以下以下例子:

void test(const int n)//虽然是const修饰,但是n的值只有在运行期间通过实参传递进来才知道其值大小,因此是只读。
{
	//字面值类型:算术类型、引用和指针都属于字面值类型,自定义类、IO库,string类型则不属于字面值类型
	int a = 10;
	const int n1 = 100;//n1被字面值100修饰,在编译期间就能确定其大小
	int array[n];//只读变量不能进行初始化数组的大小
	int array1[n1];//常量表达式可以进行初始化其大小

	const int& n2 = n1;
	int array2[n2];//n2仍然是只读,error

	int& n3 = a;//error
	int array3[n3];//n3仍然是只读

	int& n6 = a;//可以通过其他方式修改n6的大小,因此其仍然是只读变量
	int array6[n6];//error

	const int n4 = n1;
	int array3[n4];//表示常量表达式
}

        综上,对于常量的判断准则有以下三条:   

  • 只有用字面量初始化的 const 常量才会进入符号表
  • 使用其他变量初始化的 const 常量仍然是只读变量
  • 被 volatile 修饰的 const 常量不会进入符号表

二、关于constexpr

1、从本质了解constexpr

        在 C++11 中添加了一个新的关键字 constexpr,这个关键字是用来修饰常量表达式的。所谓常量表达式,指的就是由多个或一个常量组成并且在编译过程中就得到计算结果的表达式。

        C++ 程序从编写完毕到执行分为四个阶段:预处理、 编译、汇编和链接 4 个阶段,得到可执行程序之后就可以运行了。需要额外强调的是,常量表达式和非常量表达式的计算时机不同,非常量表达式只能在程序运行阶段计算出结果,但是常量表达式的计算往往发生在程序的编译阶段,这可以极大提高程序的执行效率,因为表达式只需要在编译阶段计算一次,节省了每次程序运行时都需要计算一次的时间。

int getValue()
{
	int a = 10;
	return a;
}

//constexpr 关键字之后就可以在程序中使用它来修改常量表达式,用来提高程序的执行效率。
constexpr int getValue1()//有constexp修饰,
{
	int a = 10;
	return a;
}

void test()
{
	int array[getValue()];//getValue()非常量表达式
	int array1[getValue1()];//getValue1()为常量表达式
}

 再看以下:

const int m = f();  // 不是常量表达式,m的值只有在运行时才会获取。
const int i=520;    // 是一个常量表达式
const int j=i+1;    // 是一个常量表达式
 
constexpr int i=520;    // 是一个常量表达式
constexpr int j=i+1;    // 是一个常量表达式
 

 2、constexpr修饰函数

(1)函数必须要有返回值,并且 return 返回的表达式必须是常量表达式。

// error,不是常量表达式函数
constexpr void func1()
{
    int a = 100;
    cout << "a: " << a << endl;
}
 
// error,不是常量表达式函数
constexpr int func1()
{
    int a = 100;
    return a;
}
 
 

(2)函数必须要有返回值,并且 return 返回的表达式必须是常量表达式。

#include <iostream>
using namespace std;
 
constexpr int func1();
int main()
{
    constexpr int num = func1();	// error
    return 0;
}
 
constexpr int func1()
{
    constexpr int a = 100;
    return a;
}
 
 

总结:在定义常量时,const 和 constexpr 是等价的,都可以在程序的编译阶段计算出结果。但是,在使用中建议将 const 和 constexpr 的功能区分开,即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr。

(1)const用于修饰不能被修改的对象,但const对象的值通常在程序运行期间才能确定;

(2)constexpr用于修饰常量表达式或可返回常量表达式的constexpr函数,在编译时能确定值;

(3)constexpr函数都是inline函数。

参考文献:

(161条消息) C++ const和constexpr详解_倒地不起的土豆的博客-CSDN博客_constexpr string

(161条消息) constexpr_Gamer_code的博客-CSDN博客_constexpr

(161条消息) 【C++深度解析】9、const 常量?只读变量?_-出发-的博客-CSDN博客_c++ 只读变量《C++ Primer 第五版》

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值