const与constexpr

  • const

    • 用于声明常量变量,可以在编译时或运行时初始化。
    • 适用于需要在运行时确定值的情况。
    • 不能用于需要编译时常量表达式的地方。
  • constexpr

    • 用于声明编译时常量变量和函数。
    • 确保值在编译时确定。
    • 适用于需要编译时常量表达式的地方,如数组大小、枚举值、模板参数等。

const

  1. 定义

    • const 关键字用于声明常量,表示该变量或对象的值在初始化后不能被修改。
  2. 编译时 vs 运行时

    • const 变量可以在编译时或运行时初始化。如果在编译时可以确定其值,编译器可以将其视为常量,但并不是强制要求。

    • 例如:

      复制代码
      const int a = 10; // 编译时初始化
      const int b = someFunction(); // 运行时初始化
  3. 使用场景

    • 用于声明常量变量、常量指针和常量引用。

    • 可以用于函数参数,表示该参数在函数体内不会被修改。

    • 例如:

      复制代码
      void print(const std::string& s); // s 在函数体内不会被修改
      const int* ptr; // 指针 ptr 指向的数据不能被修改
      int* const ptr = &x; // 指针 ptr 不能被修改,但其指向的数据可以被修改
  4. 限制

    • const 变量可以在运行时初始化,因此不一定能在编译时确定其值。

    • 不能用于需要编译时常量表达式的地方,如数组大小、枚举值等。

    • 例如:

      复制代码
      int x = 10;
      const int y = x;
      int arr[y]; // 错误:y 不是编译时常量

constexpr

  1. 定义

    • constexpr 关键字用于声明可以在编译时计算的常量表达式,确保其值在编译时确定。
  2. 编译时 vs 运行时

    • constexpr 变量必须在编译时初始化,并且其值必须在编译时可以确定。

    • 例如:

      复制代码
      constexpr int a = 10; // 编译时初始化
      constexpr int b = someConstexprFunction(); // 编译时初始化
  3. 使用场景

    • 用于声明编译时常量变量。

    • 用于声明编译时常量函数,这些函数必须在编译时可求值。

    • 用于数组大小、枚举值、模板参数等需要编译时常量表达式的地方。

    • 例如:

      复制代码
      constexpr int size = 10;
      int arr[size]; // 正确:size 是编译时常量
  4. 限制

    • constexpr 函数必须满足一定的条件,如只能包含返回语句、变量声明、表达式求值等简单的语句,并且所有操作都必须在编译时可求值。

    • 例如:

      复制代码
      constexpr int add(int a, int b) {
          return a + b; // 正确:简单的表达式求值
      }
      
      constexpr int complexFunction() {
          int x = 10;
          if (x > 5) {
              return x;
          } else {
              return 0;
          }
          // 错误:包含复杂的控制流
      }

示例代码

复制代码
#include <iostream>

// const 示例
const int a = 10;
int getRuntimeValue() {
    return 20;
}
const int b = getRuntimeValue(); // 运行时初始化

// constexpr 示例
constexpr int c = 30;
constexpr int add(int x, int y) {
    return x + y;
}
constexpr int d = add(10, 20); // 编译时初始化

int main() {
    std::cout << "a: " << a << std::endl; // 10
    std::cout << "b: " << b << std::endl; // 20
    std::cout << "c: " << c << std::endl; // 30
    std::cout << "d: " << d << std::endl; // 30

    int arr[c]; // 正确:c 是编译时常量
    // int arr2[b]; // 错误:b 不是编译时常量

    return 0;
}
相关推荐
2401_8920709818 小时前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei18 小时前
Visual Studio 配置C++opencv
c++·学习·visual studio
不爱吃炸鸡柳19 小时前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发19 小时前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
‎ദ്ദിᵔ.˛.ᵔ₎19 小时前
STL 栈 队列
开发语言·c++
2401_8920709820 小时前
【Linux C++ 日志系统实战】高性能文件写入 AppendFile 核心方法解析
linux·c++·日志系统·文件写对象
郭涤生20 小时前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿20 小时前
vector
c语言·开发语言·数据结构·c++·算法
cccyi720 小时前
【C++ 脚手架】etcd 的介绍与使用
c++·服务发现·etcd·服务注册
liu****20 小时前
第16届省赛蓝桥杯大赛C/C++大学B组(京津冀)
开发语言·数据结构·c++·算法·蓝桥杯