C++ constexpr

定义

  1. C++11新增语法
  2. 编译器常量,在编译器求值
  3. constexpr函数或变量必须满足一定条件才能在编译期求值。constexpr只能进行简单操作(算术运算、逻辑运算) ,不能包含运行时才能确定的操作,如内存分配、文件读取

const对比

以前的const修饰符并不能保证产生编译期常量,因此某些用法,比如用const常量声明数组长度不能保证可行。相比之下,constexpr类型具有更强的编译期检查,可以在编译阶段就发现常量能否在编译阶段确定

example

  1. 无法初始化std::vectorstd::list
    1. std::vector为例,它在内部管理着一块动态分配的连续内存区域来存储元素。在创建std::vector对象时,它会根据需要分配内存,这个过程涉及到运行时的内存分配操作,无法在编译期完成
    2. 例如,constexpr std::vector<int> v = {1, 2, 3};会报错。因为std::vector的构造函数需要在运行时确定内存分配的大小和位置,即使提供了初始化列表,也无法在编译期确定这些内存相关的操作。
    3. 代替方案 :可以考虑使用std::arraystd::array是一个固定大小的数组容器,它的大小在编译期是确定的,可以用于替代std::vector在编译期常量场景下的部分功能。例如,constexpr std::array<int, 3> a = {1, 2, 3};是合法的
  2. 无法初始化std::stringQString
    1. std::string是一个类类型,它的构造涉及到动态内存分配 (用于存储字符串内容)等运行时操作。例如,当创建一个std::string对象时,它会在堆上分配内存来存储字符序列,这个过程是在运行时发生的,无法在编译期完成
    2. C++标准库在设计时没有为 std::string 提供 constexpr 构造函数。在 C++20 之前,标准库中的大部分容器类都不能使用 constexpr 构造函数
    3. 代替方案 :可以使用const char*const char[],形如constexpr std::string str = "hello";
    4. 代替方案std::string_view(C++17)是一个轻量级的字符串视图类,它不拥有字符串的内容,只是提供了对字符串内容的查看功能 。在某些情况下,可以将std::string_view作为编译期常量来处理字符串
      1. 不过需要注意的是,std::string_view本身只是一个视图,如果要将其转换为std::string,仍然可能涉及到运行时操作,如复制字符串内容到新的std::string对象中。但在只需要查看字符串内容而不涉及修改和存储的场景下,std::string_view可以作为一种编译期常量来使用
  3. 无法初始化输入/输出(I/O)操作的类型(如std::ofstreamstd::ifstream等)
    1. std::ofstream(用于输出文件流)和std::ifstream(用于输入文件流)这样的类型,它们的操作本质上依赖于外部设备(如硬盘上的文件)和运行时的系统调用 。例如,当打开一个文件流时,需要在运行时查找文件系统中的文件、获取文件句柄等操作,这些操作无法在编译期完成。如constexpr std::ofstream out("output.txt");是非法的,因为在编译期无法执行打开文件并建立输出流的操作。
    2. 替代方案 :如果只是需要在编译期确定一些文件相关的常量信息,比如文件名,可以使用constexpr const char*来表示文件名。例如,constexpr const char* filename = "output.txt";,然后在运行时使用这个常量来打开文件流,如std::ofstream out(filename);
  4. 无法初始化大多数自定义类(如果其构造函数涉及非constexpr操作)
    1. 对于自定义类,如果其构造函数包含运行时操作,如动态内存分配、调用非constexpr函数、等待用户输入等,那么这个类就不能在编译期初始化 。例如,假设有一个自定义类MyClass,其构造函数如下:

      cpp 复制代码
      class MyClass {
      public:
         MyClass() {
             // 动态分配内存
             data = new int;
         }
      private:
         int* data;
      };

      对于这样的类,constexpr MyClass obj;是不合法的,因为其构造函数中的动态内存分配操作无法在编译期完成

    2. 替代方案 :要使自定义类能够在编译期初始化,需要确保其构造函数中的操作都是可以在编译期完成的。需要修改构造函数,避免动态内存分配等运行时操作。例如,可以将上述MyClass的构造函数修改为使用静态存储的成员变量,或者使用constexpr函数来初始化成员变量等方式,使其符合编译期初始化的要求

相关推荐
会周易的程序员4 分钟前
软件接入大模型实现 Agent —— 从原理到 C++ 落地完全指南
c++·人工智能·物联网·架构·agent·工业协议·mcp
Dovis(誓平步青云)7 分钟前
牛奶不能减成负数:冰箱库存的筛选、去重与不可变更新
android·java·开发语言
OPEN-F9 分钟前
Python进阶教程:算法与数据结构入门
开发语言·python
薛定猫AI19 分钟前
【技术干货】Claude Code多模型代理与反馈闭环:Python实现可验证的AI编程工作流
开发语言·python·ai编程
XR12345678820 分钟前
工厂车间无线网络怎么选?AGV 与复杂环境是分水岭
开发语言·php
hetao173383722 分钟前
2026-08-21~23 hetao1733837 的刷题记录
c++·算法
zq_638926 分钟前
利用 MATLAB 调用 STK Object Model COM 显示雷达受干扰前后探测范围的变化
开发语言·matlab
大黄说说40 分钟前
类型安全时代:PHP 8+ 的联合类型、交集类型与泛型(模板)最佳实践
开发语言·安全·php
小弥儿1 小时前
GPT Image 2 提示词库,把散落的生图提示词变成工程资产
开发语言·javascript·gpt·学习
空堂与归2 小时前
单机 Python 跑不动?Ray 分布式计算框架让 AI 训练提速 10 倍
开发语言·人工智能·python