C++ 常量表达式完全指南:编译时求值与优化策略

常量表达式基础

运行时与编译时求值

在第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可以在编译时或运行时求值

最佳实践与注意事项

编译时求值的分类

求值可能性分为四类:

  1. 从不:非常量表达式
  2. 可能:基于"视同规则"优化
  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{}; // 额外加分题

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"