0

0

如何在c++中实现编译期计算? (constexpr函数)

尼克

尼克

发布时间:2026-01-23 16:09:10

|

526人浏览过

|

来源于php中文网

原创

constexpr函数需满足:函数体仅含声明、return、字面量运算及constexpr函数调用;禁用try、goto、static变量、非字面量类型;参数与返回值须为字面量类型;不可调用非constexpr函数;递归深度受编译器限制。

如何在c++中实现编译期计算? (constexpr函数)

constexpr 函数必须满足哪些约束?

不是所有函数加个 constexpr 就能进编译期。它本质是“编译器可静态求值的纯函数”,核心限制有:
函数体只能包含声明、return、字面量运算、其他 constexpr 函数调用;不能有 trygotostatic 变量、非字面量类型成员;C++14 起允许有限循环和局部变量,但所有操作仍需在编译期可判定。

  • 返回类型和所有参数类型必须是字面量类型(intstd::array、用户定义的带 constexpr 构造函数的类等)
  • 函数体内不能调用非 constexpr 函数(比如 std::sqrt 在 C++20 前不是 constexpr
  • 递归深度受编译器限制(如 GCC 默认 512 层),过深会报错 constexpr evaluation exceeded maximum depth

如何写一个真正能在编译期展开的阶乘函数?

下面是一个 C++14 兼容的 constexpr 阶乘实现,它在模板实例化或变量初始化时触发编译期计算:

constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

// 编译期使用示例 constexpr int fact_5 = factorial(5); // OK:5! = 120,存为字面量 static_assert(fact_5 == 120, "compile-time check");

// 错误用法(运行时输入无法用于 constexpr 上下文) // int x = 5; // constexpr int bad = factorial(x); // ❌ error: 'x' is not a constant expression

注意:factorial(5) 在编译时就被替换成 120,生成的汇编里不会出现任何乘法指令;而若传入变量或未标记 constexpr 的表达式,编译器会退化为运行时调用(C++14+)或直接报错(C++11)。

为什么 std::array 的 size() 不是 constexpr?

这是常见误解点:std::array::size() 在 C++17 前**不是** constexpr,导致类似 std::array{}.size() 无法用于模板非类型参数。原因在于早期标准未将该成员函数标注为 constexpr —— 它只是返回 N,但语言规则没允许。

立即学习C++免费学习笔记(深入)”;

Soundful
Soundful

Soundful Ai音乐生成器,只需一个按钮即可生成免版税曲目

下载
  • C++17 起 std::array::size() 已是 constexpr,可安全用于模板参数,如:template void f(std::array); f(arr);
  • 若需兼容旧标准,应直接用 std::array::size() 的模板参数 N,而非调用成员函数
  • 自定义容器务必显式加 constexpr 标签,否则即使逻辑简单也不会被编译器信任

constexpr 和 consteval 的关键区别在哪?

consteval(C++20 引入)是更严格的“仅编译期”保证:它强制函数**必须**在编译期求值,任何运行时调用都会编译失败。而 constexpr 是“可编译期,也可运行时”——取决于调用上下文。

consteval int square(int x) {
    return x * x;
}

constexpr int cube(int x) { return x x x; }

int main() { constexpr int s1 = square(4); // ✅ OK // int s2 = square(4); // ❌ error: call to consteval function 'square' is not a constant expression

constexpr int c1 = cube(4);     // ✅ 编译期
int c2 = cube(4);               // ✅ 运行时(允许)

}

实际项目中,优先用 constexpr 保持灵活性;只有当你明确禁止运行时路径(例如实现元编程断言、生成唯一编译期哈希),才用 consteval。别为了“看起来更编译期”而滥用 consteval,它会显著降低函数复用性。

相关专题

更多
go语言goto的用法
go语言goto的用法

本专题整合了go语言goto的用法,阅读专题下面的文章了解更多详细内容。

133

2025.09.05

python如何计算数的阶乘
python如何计算数的阶乘

方法:1、使用循环;2、使用递归;3、使用math模块;4、使用reduce函数。更多详细python如何计算数的阶乘的内容,可以阅读下面的文章。

170

2023.11.13

python求阶乘教程大全
python求阶乘教程大全

本专题整合了python求阶乘相关教程,阅读专题下面的文章了解更多详细内容。

10

2025.11.08

python语言求阶乘
python语言求阶乘

本专题整合了python中阶乘相关教程,阅读专题下面的文章了解更多详细步骤。

28

2025.12.06

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

358

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

542

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号