
各位读者大佬好,我是落羽!一个坚持不断学习进步的学生。 如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步! 也欢迎关注我的blog主页: 落羽的落羽
现代C++,从C++11开始,引入了常量表达式和constexpr关键字的概念,并且在之后的C++标准中不断更新
常量表达式是指,值不会改变并且在编译过程中就能得到计算结果的表达式。用字面量、常量表达式初始化的const对象都是常量表达式。但是用变量初始化的const对象不是常量表达式。
const int a = 1; //a是常量表达式
const int b = a + 1; //b是常量表达式
int c = 1; //c不是常量表达式
const int d = c; //d不是常量表达式,因为可能有代码影响c的值,编译时期无法确定c的值由于常量表达式的值在编译时期就能确定,编译器在这里就能进行优化,在使用常量表达式的地方直接进行替换值,通过汇编语言我们能看出区别:

常量表达式的最大优点就是能将一些计算从运行时转移到编译时,提升程序运行时的性能。
C++11引入了一个关键字:constexpr,用于指定常量表达式,它允许在编译时计算表达式的值。 constexpr可以修饰变量,但修饰的变量一定要是常量表达式,且必须用常量或常量表达式进行初始化,否则会报错

constexpr也可以修饰指针,但修饰的是指针本身,也是就顶层const。
const可以分为顶层const、底层const。本身被const修饰叫做顶层const、指向的对象被const修饰叫做底层const。大多数普通对象被const修饰时都是顶层const;指针被const修饰时,
*左边的const叫做底层const,*右边的const叫做顶层const;const修饰引用时,是底层const
constexpr可以修饰函数,constexpr函数默认都是inline的,函数的计算会由编译器在编译时期执行。但是,一个函数的逻辑可比表达式的逻辑复杂多了,这对于编译器的要求就更加严格,因此在C++11的标准中,对constexpr修饰的函数要求也十分严格:
constexpr函数的返回结果,必须用一个常量表达式进行接收,才能触发编译器的优化。否则这个函数还是像普通函数一样,在运行调用时才会计算:
constexpr int func1()
{
return 1;
}
constexpr int func2(int x)
{
return x + 10;
}
constexpr int func3(int n)
{
return n <= 1 ? 1 : n * func3(n - 1);
}
int main()
{
constexpr int a = func1();
constexpr int b = func2(10);
constexpr int c = func3(5);
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}通过汇编语句观察,确实在编译时期就计算出了a、b、c的结果,在cout语句中直接进行了值替换

constexpr还能修饰其他函数:
()后要加上const,函数内不能修改成员变量能看出来,C++11对于constexpr修饰函数还是相当相当严格的,但这些规定会在后面的C++标准中逐步放开,时代还是在进步的~
C++14中,大幅放宽了对constexpr函数的限制,使其语法和功能更接近普通函数:
std::array容器、等更多复合类型实验时,要确保编译器支持的是C++14标准:

constexpr int func(int n)
{
if (n == 1 || n == 2)
{
return n;
}
int ret = 1; //允许局部变量
for (int i = 2; i <= n; i++)
{
ret *= i;
}
return ret; //允许多条return语句
}
int main()
{
constexpr int a = func(5);
cout << a << endl;
return 0;
}
C++17进一步对constexpr扩展,使其能力大幅提升,进一步模糊了编译时和运行时的界限。
其中,constexpr可以修饰lambda表达式了,要求:
同样,实验时保证编译器是C++17标准的:

int main()
{
constexpr int a = 10;
constexpr auto func = [a](int x) constexpr {return x * a; };
constexpr int b = func(5);
cout << b << endl;
return 0;
}
C++20是C++的最重要的更新之一,也同样对constexpr特性进行了革命,使编译器的计算能力得到前所未有的提升,使其成为现代C++元编程和性能优化的核心工具,主要更新了以下内容:
mutable关键字,这个成员变量就能在constexpr成员函数中被修改了。C++23是目前最新的C++标准,但编译器支持仍在路上,主要因为标准本身的复杂性、厂商对稳定性的优先考量以及实现策略的差异。让我们期待C++的未来无限发展可能吧!
本篇完,感谢阅读