C++ 常量全面讲解

C++ 常量全面讲解

常量指程序运行期间值不能被修改 的量,C++ 分为字面常量 、const 常量、constexpr 常量、#define 宏常量、枚举常量几大类。


一、字面常量(直接写出的值)

程序中直接书写的数值、字符、字符串,本身就是常量,无法修改。

1. 整型字面量

cpp 复制代码
100;        // 十进制 int
012;        // 八进制(以 0 开头)
0x1A;       // 十六进制(以 0x/0X 开头)
100L;       // long 类型
100LL;      // long long 类型
100U;       // unsigned 无符号

2. 浮点字面量

cpp 复制代码
3.14;       // double(默认)
3.14f;      // float 单精度
3.14L;      // long double

3. 字符 & 字符串字面量

cpp 复制代码
'A';        // 字符常量,1字节
"hello";    // 字符串常量,末尾自带 '\0'
'\n';       // 转义字符常量

4. 布尔字面量

cpp 复制代码
true;
false;

特点:没有变量名,只能直接使用,不可赋值修改。


二、#define 宏常量(预处理常量)

C 语言风格,C++ 兼容,预处理阶段直接文本替换。

语法

cpp 复制代码
#define 常量名  值

示例

cpp 复制代码
#include <iostream>
#define PI 3.1415926
#define MAX_NUM 100

int main() {
    double r = 2;
    double s = PI * r * r;
    std::cout << s;
    // PI = 10;  // 报错,宏不能修改
    return 0;
}

优缺点

✅ 优点:使用简单,全局生效

❌ 缺点:

  1. 无类型检查,只是纯文本替换,易出bug
  2. 不具备作用域,全局污染
  3. 无法调试

C++ 不推荐优先使用 ,优先用 const/constexpr。


三、const 修饰常量(C++ 核心常用)

1. 基本语法

cpp 复制代码
const 数据类型 常量名 = 值;

必须初始化,一旦定义,值永久不可修改。

基础示例

cpp 复制代码
#include <iostream>
int main() {
    const int a = 10;
    // a = 20;  // 编译报错:const 常量不可修改

    const double PI = 3.14159;
    std::cout << PI;
    return 0;
}

2. const 作用域

  • 局部 const:作用域仅限当前代码块
  • 全局 const:默认仅当前文件可见(和普通全局变量不同)

3. 结合指针(高频考点)

区分 const 修饰指针本身 和 修饰指向的内容:

cpp 复制代码
// 1. 常量指针:指向的值不可改,指针本身可改
const int* p1;
int x = 1, y = 2;
p1 = &x;
// *p1 = 100;  // 报错

// 2. 指针常量:指针本身不可改,指向的值可改
int* const p2 = &x;
*p2 = 100;
// p2 = &y;    // 报错

// 3. 双重 const:指针、指向的值都不可改
const int* const p3 = &x;

4. const 修饰函数参数/返回值

  • 形参加 const:保证函数内不会修改实参内容
cpp 复制代码
void func(const std::string& str) {
    // str = "abc"; 报错
}

四、constexpr 常量(C++11 新增,编译期常量)

constexpr 表示编译阶段就能确定值 的常量,比单纯 const 语义更明确。

1. 基本用法

cpp 复制代码
constexpr int NUM = 200;
constexpr double PI = 3.14159;

2. 和 const 的核心区别

  1. const

    • 可以是编译期常量 ,也可以是运行时常量

    • 允许用变量初始化:

      cpp 复制代码
      int a = 10;
      const int b = a; // 运行时确定值
  2. constexpr

    • 强制要求编译期确定值,只能用常量/常量表达式初始化

    • 可用于数组大小、模板参数等必须编译期求值的场景:

      cpp 复制代码
      constexpr int len = 10;
      int arr[len]; // 合法,C++ 要求数组大小为编译期常量

3. constexpr 函数(C++11 起)

函数也可声明为 constexpr,编译期就能计算结果:

cpp 复制代码
constexpr int add(int a, int b) {
    return a + b;
}
int arr[add(2,3)]; // 合法

总结:

  • 单纯定义常量:C++11 及以后优先用 constexpr
  • 仅做只读保护(运行时确定值):用 const

五、枚举常量 enum

用枚举定义一组相关整型常量。

1. 普通枚举

cpp 复制代码
enum Color {
    RED,    // 默认 0
    GREEN,  // 1
    BLUE    // 2
};
// RED、GREEN、BLUE 都是整型常量
int a = RED;

2. 手动指定值

cpp 复制代码
enum Num {
    ONE = 1,
    TEN = 10,
    HUNDRED = 100
};

3. 强类型枚举 enum class(C++11 推荐)

解决普通枚举隐式转 int、命名冲突问题:

cpp 复制代码
enum class Week {
    MON, TUE, WED
};
Week w = Week::MON; // 必须加作用域

六、const / #define / constexpr 对比表

方式 类型检查 作用域 求值时机 推荐度
#define 无 全局 预处理 不推荐
const 有 局部/文件 编译/运行 兼容旧代码
constexpr 有 局部/文件 编译期 C++11+首选

七、补充规则

  1. 常量定义后绝对不能赋值修改,编译直接报错;
  2. 全局常量建议放在头文件,配合 const/constexpr 使用;
  3. 数组、模板参数等场景,必须使用编译期常量 (constexpr 或字面量);
  4. 字符串常量存放在只读数据区,禁止通过指针修改内容。
相关推荐
代码山河26 分钟前
基本类型转换:自动类型转换与强制类型转换
java·学习·架构·教程·面向对象·项目
老歌老听老掉牙29 分钟前
圆柱端面四平面交线及其在yoz面投影的几何解析与 Python 实现
开发语言·python·平面
繁星蓝雨35 分钟前
C++设计原理———多重继承(虚基类、菱形继承、委托、重命名、基类和成员初始化)
c++·委托·多重继承·mi·显式初始化列·虚基类·对象布局
旖旎夜光1 小时前
【C++ 基础入门】命名空间、输入输出、缺省参数与函数重载
开发语言·c++·笔记·学习
俩个逗号。。1 小时前
Kotlin flow 详解
android·开发语言·kotlin
Escalating_xu2 小时前
【Linux 网络编程】五种 I/O 模型与非阻塞 I/O:从“等数据”到正确处理 EAGAIN
java·linux·网络
程序猿乐锅2 小时前
万字详解Single-flight(单飞模式)
java·开发语言·分布式·后端·学习·single-flight
扶尔魔ocy2 小时前
【QT入门到晋级】用开源的自定义控件开发
c++·qt·自定义控件
Java后端的Ai之路2 小时前
【AIAgent开发】-Agent工具封装成CLI(纯干货!!!)
java·javascript·人工智能·agent·cli
AntsData3 小时前
用 12K+ 条亚马逊评论信号,定位机械键盘下一版该改什么
java·大数据·计算机外设