导读:本期聚焦于小伙伴创作的《C++中的constexpr有什么用?一文搞懂编译期常量表达式与元编程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++中的constexpr有什么用?一文搞懂编译期常量表达式与元编程》有用,将其分享出去将是对创作者最好的鼓励。

constexpr是C++11标准引入的关键字,核心作用是标识可以在编译阶段完成求值的表达式、变量或者函数,让原本运行期执行的计算提前到编译期完成,既减少运行时的计算开销,也能让编译器做更多优化。它和传统的const关键字有本质区别,const只是保证变量运行期不可修改,而constexpr要求表达式在编译期就必须能确定结果。

C++中的constexpr有什么用?一文搞懂编译期常量表达式与元编程

constexpr的核心作用

1. 定义编译期常量

使用constexpr修饰的变量,必须在编译期就能确定初始值,编译器会直接把这个值嵌入到生成的二进制代码中,不会为它分配运行时的内存空间。比如下面这个例子:

#include <iostream>

// 编译期常量,编译时就能确定值为100
constexpr int MAX_SIZE = 100;

int main() {
    // 可以用constexpr常量定义数组大小,这是普通const变量做不到的
    int arr[MAX_SIZE] = {0};
    std::cout << "数组大小: " << MAX_SIZE << std::endl;
    return 0;
}

2. 定义编译期可求值函数

constexpr修饰的函数,当传入的参数是编译期常量时,函数会在编译期执行并返回结果,否则会退化为普通运行期函数。这种特性让我们可以把简单的计算逻辑封装成函数,同时保证编译期可用的场景能正常求值。

#include <iostream>

// constexpr函数,计算两个整数的和
constexpr int add(int a, int b) {
    return a + b;
}

int main() {
    // 传入编译期常量,编译期就能算出结果,相当于直接写30
    constexpr int sum = add(10, 20);
    std::cout << "求和结果: " << sum << std::endl;

    int x = 10, y = 20;
    // 传入运行期变量,函数会在运行期执行
    int run_sum = add(x, y);
    std::cout << "运行期求和结果: " << run_sum << std::endl;
    return 0;
}

3. 支持编译期构造对象

constexpr还可以修饰类的构造函数,只要构造函数的所有参数都是编译期常量,并且构造函数内部没有运行期才能执行的操作,就可以在编译期创建该类的对象。比如下面这个简单的坐标类:

#include <iostream>

class Point {
public:
    // constexpr构造函数
    constexpr Point(int x, int y) : x_(x), y_(y) {}
    constexpr int get_x() const { return x_; }
    constexpr int get_y() const { return y_; }
private:
    int x_;
    int y_;
};

int main() {
    // 编译期构造Point对象
    constexpr Point p(10, 20);
    constexpr int x = p.get_x();
    constexpr int y = p.get_y();
    std::cout << "坐标x: " << x << ", 坐标y: " << y << std::endl;
    return 0;
}

constexpr与元编程的结合

元编程指的是在编译期生成或者操作代码的编程方式,传统的C++元编程主要依赖模板特化,语法复杂且可读性差。constexpr出现后,我们可以用更直观的函数式写法实现编译期元编程,大幅降低元编程的门槛。

比如要计算斐波那契数列的第n项,用传统模板元编程需要写特化版本,而用constexpr函数只需要几行代码:

#include <iostream>

// constexpr递归计算斐波那契数列
constexpr int fib(int n) {
    if (n <= 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}

int main() {
    // 编译期计算斐波那契第10项,结果直接嵌入二进制
    constexpr int fib10 = fib(10);
    std::cout << "斐波那契第10项: " << fib10 << std::endl;
    return 0;
}

上面的fib函数在传入编译期常量n时,递归过程会在编译期完成,不会占用运行时的栈空间和计算资源。如果是运行期传入n,函数会正常在运行期执行递归逻辑。

constexpr的使用注意事项

  • constexpr变量必须有初始值,且初始值必须是编译期可求值的表达式,不能是运行期才能确定的值,比如用户输入、函数运行期返回值等。
  • constexpr函数内部在C++11标准下只能有一条return语句,不能有循环、局部变量等复杂逻辑,C++14及之后标准放宽了限制,允许函数内有循环、变量定义等操作,只要整体能在编译期求值即可。
  • constexpr构造函数初始化的所有成员变量,都必须是内置类型或者也有constexpr构造函数的自定义类型,否则无法在编译期创建对象。
  • 如果不确定一个表达式是否能在编译期求值,可以用static_assert配合constexpr表达式做编译期检查,比如static_assert(MAX_SIZE == 100, "MAX_SIZE值错误");,如果表达式不成立会直接编译报错。

constexpr和const的区别

很多开发者容易混淆const和constexpr,两者的核心差异如下:

对比项constconstexpr
求值阶段运行期保证值不可修改,初始值可以是运行期确定的编译期必须能确定值,否则编译报错
数组大小定义不能直接作为数组大小(C++不支持变长数组的情况下)可以直接作为数组大小,因为编译期已知值
函数修饰修饰成员函数表示该函数不会修改对象成员修饰函数表示该函数可以在编译期求值
对象构造可以修饰运行期构造的对象只能修饰编译期可构造的对象

实际开发中,如果确定某个变量、函数或者对象需要在编译期确定值,优先使用constexpr,这样既能获得编译期优化的好处,也能让代码的语义更清晰,明确告诉其他开发者这个表达式是编译期常量。

constexprC++编译期常量元编程常量表达式修改时间:2026-07-17 05:45:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。