常量表达式基础
运行时与编译时求值
在第1.10课——表达式简介中,我们介绍了表达式。默认情况下,表达式在运行时求值。在某些情况下,它们必须这样做:
std::cin >> x;
std::cout << 5 << '\n';
编译时优化示例
const double x { 1.2 };
const double y { 3.4 };
const double z { x + y }; // x + y 可能在运行时求值,也可能在编译时求值
编译时编程的优势
性能提升与代码质量
编译时编程带来的好处:
- 性能:程序更小、更快
- 通用性:可在需要编译时值的地方使用
- 可预测性:编译时错误检测
- 质量:避免未定义行为
编译时编程基础特性
主要包括:
- constexpr 变量
- constexpr 函数
- 模板
- static_assert
常量表达式详解
常量表达式的定义与组成
常量表达式可以包含:
- 字面量(如'5’,‘1.2’)
- 常量表达式操作数的运算符
- 常量整型变量
- constexpr变量
- constexpr函数调用
不允许的表达式元素
以下内容不能用于常量表达式:
// 示例:不允许的表达式
非常量变量
const double d { 1.2 }; // 常量非整型变量
非constexpr函数返回值
函数参数
常量表达式实践指南
示例与应用
#include <iostream>
int getNumber()
{
std::cout << "Enter a number: ";
int y{};
std::cin >> y; // 只能在运行时执行
return y; // 这个返回表达式是运行时表达式
}
int five()
{
return 5; // 这个返回表达式是常量表达式
}
编译时求值规则
// 必须在编译时求值的例子
const int x { 3 + 4 }; // 常量表达式3 + 4必须在编译时求值
int y { 3 + 4 }; // 常量表达式3 + 4可以在编译时或运行时求值
最佳实践与注意事项
编译时求值的分类
求值可能性分为四类:
- 从不:非常量表达式
- 可能:基于"视同规则"优化
- 可能:非必需上下文的常量表达式
- 总是:必需上下文的常量表达式
调试与优化平衡
需要考虑:
- 编译时求值对调试的影响
- 编译器优化的灵活性
- 开发时间与运行时性能的平衡
测验与练习
表达式分析练习
分析以下表达式:
char a { 'q' };
const int b { 0 };
const double c { 5.0 };
const int d { a * 2 }; // a定义为char a { 'q' };
int e { c + 1.0 }; // c定义为const double c { 5.0 };
const int f { d * 2 }; // d定义为const int d { 0 };
const int g { getNumber() }; // getNumber按值返回一个int
const int h{}; // 额外加分题