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函数来初始化成员变量等方式,使其符合编译期初始化的要求

相关推荐
程序员弘羽15 分钟前
C++ 第四阶段 内存管理 - 第二节:避免内存泄漏的技巧
java·jvm·c++
【ql君】qlexcel21 分钟前
Notepad++ 复制宏、编辑宏的方法
开发语言·javascript·notepad++··宏编辑·宏复制
Zevalin爱灰灰30 分钟前
MATLAB GUI界面设计 第六章——常用库中的其它组件
开发语言·ui·matlab
冰糖猕猴桃38 分钟前
【Python】进阶 - 数据结构与算法
开发语言·数据结构·python·算法·时间复杂度、空间复杂度·树、二叉树·堆、图
wt_cs1 小时前
银行回单ocr api集成解析-图像文字识别-文字识别技术
开发语言·python
_WndProc1 小时前
【Python】Flask网页
开发语言·python·flask
liujing102329292 小时前
Day04_刷题niuke20250703
java·开发语言·算法
DolphinDB2 小时前
如何在C++交易系统中集成高性能回测与模拟撮合
c++
能工智人小辰2 小时前
二刷 苍穹外卖day10(含bug修改)
java·开发语言
DKPT2 小时前
Java设计模式之结构型模式(外观模式)介绍与说明
java·开发语言·笔记·学习·设计模式