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

相关推荐
jimin_callon2 分钟前
VBA第三十八期 VBA自贡分把表格图表生成PPT
开发语言·python·powerpoint·编程·vba·deepseek
愚戏师1 小时前
软件工程(应试版)图形工具总结(二)
数据结构·c++·python·软件工程
owde1 小时前
顺序容器 -forward list单链表
数据结构·c++·list
矛取矛求1 小时前
C++ 标准库参考手册深度解析
java·开发语言·c++
lmy201211081 小时前
GESP:2025-3月等级8-T1-上学
c++·算法·图论·dijkstra
٩( 'ω' )و2601 小时前
stl_list的模拟实现
开发语言·c++·list
&Sinnt&1 小时前
C++/Qt 模拟sensornetwork的工作
c++·qt
奕天者1 小时前
C++学习笔记(三十三)——forward_list
c++·笔记·学习
麻芝汤圆2 小时前
MapReduce 的广泛应用:从数据处理到智能决策
java·开发语言·前端·hadoop·后端·servlet·mapreduce
珊瑚里的鱼2 小时前
第五讲(下)| string类的模拟实现
开发语言·c++·笔记·程序人生·算法·visualstudio·visual studio