C++ const 完整语法整理

C++ const 完整语法整理

const 是 C++ 核心的类型限定符,核心作用是给数据 / 函数添加 “只读” 约束,编译阶段强制检查修改行为,既提升代码安全性、可读性,也帮助编译器做优化。以下按「使用场景」拆解const的语法、作用和核心规则,覆盖从基础到类成员的全场景。

一、核心定义

const(常量)本质是 “只读契约”:

  • 编译期检查:禁止修改被const修饰的内容,违规直接报编译错误;
  • 无运行期开销:仅在编译阶段生效,不额外占用内存(除非对const变量取地址 / 声明为全局 / 静态);
  • 核心价值:避免意外篡改数据、明确函数 “只读行为”、支持 const 对象调用。

二、分场景语法详解

场景 1:const 修饰普通变量(全局 / 局部)

语法(两种等价写法)
// 写法1:const 在前(推荐,语义更清晰) const 类型 变量名 = 初始值; // 写法2:const 在后(效果一致,顺序不影响) 类型 const 变量名 = 初始值; 
核心作用

变量一旦初始化,终身不可修改;且const变量必须初始化(否则编译报错)。

示例

 

// 局部const变量(栈上) const double PI = 3.14159; // PI = 3.14; // 错误:只读变量不可赋值 int const num = 10; // 等价于const int num // 全局const变量(全局区,默认作用域为当前文件) const int GLOBAL_NUM = 100; // 跨文件访问全局const:加extern extern const int GLOBAL_NUM2 = 200; 
注意事项
  • 局部const变量:若用字面量初始化(如3.14),编译器可能 “常量折叠”(直接替换值,不访问内存);
  • 全局const变量:默认带static属性(仅当前文件可见),跨文件访问需加extern

场景 2:const 修饰指针(重点!三种核心场景)

核心口诀:左数右指

  • const*左边 → 修饰「指针指向的内容」(数据只读,指针可移动);
  • const*右边 → 修饰「指针本身」(指针地址只读,指向的内容可改);
场景语法核心约束示例
数据只读,指针可移const 类型* 指针名不能改*指针名,可改指针名const int* p = &a; // *p=20错,p=&b对
指针只读,数据可改类型* const 指针名必须初始化,可改*指针名,不能改指针名int* const p = &a; // *p=20对,p=&b错
数据 + 指针都只读const 类型* const 指针名都不可改,必须初始化const int* const p = &a; // 全只读
示例

 

int a = 10, b = 20; // 场景1:数据只读,指针可移 const int* p1 = &a; // *p1 = 30; // 错误:内容只读 p1 = &b; // 正确:指针可移动 // 场景2:指针只读,数据可改 int* const p2 = &a; *p2 = 30; // 正确:内容可改 // p2 = &b; // 错误:指针地址只读 // 场景3:全只读 const int* const p3 = &a; // *p3 = 30; // 错误 // p3 = &b; // 错误 

场景 3:const 修饰引用(const 引用)

语法
const 类型& 引用名 = 变量/常量/临时值; 
核心作用
  1. 禁止通过引用修改原变量(引用只读);
  2. 可绑定常量 / 临时值(普通引用只能绑定可修改的左值);
  3. 绑定临时值时,临时值的生命周期会被延长至引用的生命周期结束。
示例

 

int a = 10; const int& ref1 = a; // ref1 = 20; // 错误:引用只读 const int& ref2 = 100; // 正确:const引用可绑定常量 double b = 3.14; const int& ref3 = b; // 正确:临时值(int(b))绑定到const引用,生命周期延长 
典型用途

函数参数传递(避免拷贝 + 防止修改):

 

// 自定义类型参数:const& 避免拷贝,且禁止修改参数 void printCircle(const Circle& c) { cout << c.calculateArea() << endl; // 只能调用c的const成员函数 } 

场景 4:const 修饰函数参数

语法
// 基础类型(传值,const仅约束函数内) void func(const int num) { /* num不可改 */ } // 自定义类型(推荐const&,避免拷贝+防修改) void func(const Circle& c) { /* c不可改 */ } // 指针参数(const修饰指向的内容) void func(const int* p) { /* *p不可改 */ } 
核心作用
  • 禁止函数内修改参数值,提升代码安全性;
  • 对自定义类型(如Circle),结合引用(const&)可避免拷贝,大幅提升效率;
  • 基础类型(int/double)传值时加const,仅约束函数内,对外部无影响(可加可不加)。

场景 5:const 修饰函数返回值

语法与作用

仅对「指针 / 引用返回值」有实际意义(基础类型返回值是拷贝,const 无作用):

// 场景1:返回const指针(禁止修改返回的内容) const int* func1(int* arr) { return arr; } // 场景2:返回const引用(禁止外部修改类成员) class Circle { private: double radius; public: const double& getRadius() const { return radius; } }; 
示例
int arr[] = {1,2,3}; const int* p = func1(arr); // *p = 10; // 错误:返回的指针指向内容只读 Circle c(5.0); // c.getRadius() = 10; // 错误:返回的引用只读 

场景 6:const 修饰类成员(核心!分变量 + 函数)

子场景 6.1:const 成员变量(类内常量)
语法(两种初始化方式)
  • C++11 及以上:类内直接初始化(简洁);
  • 所有 C++ 版本:构造函数初始化列表初始化(兼容推荐)。
// 写法1:C++11+ 类内直接初始化 class Circle { private: const double PI = 3.14159; // 类内初始化const成员 double radius; public: Circle(double r) : radius(r) {} }; // 写法2:初始化列表初始化(兼容所有版本) class Circle { private: const double PI; // 仅声明,不赋值 double radius; public: // 必须在初始化列表初始化const成员(不能在构造函数体赋值) Circle(double r) : PI(3.14159), radius(r) {} }; 
关键补充:静态 const 成员变量

若常量是所有对象共享的(如 PI),加static修饰,减少内存开销(所有对象共用一份):

class Circle { private: static const double PI = 3.14159; // 静态常量,类内初始化 double radius; }; // (可选)类外定义(若需跨文件访问) const double Circle::PI = 3.14159; 
子场景 6.2:const 成员函数(常量成员函数)
语法
返回值 函数名(参数列表) const; // const在参数列表后 
核心作用
  1. 约束函数不修改对象状态this指针变为const 类名*(只读指针),不能修改类的非mutable成员变量;
  2. 支持 const 对象调用:const 对象只能调用 const 成员函数(非 const 对象可调用 const / 非 const 函数);
  3. 语义标注:明确函数是 “只读操作”,提升可读性。
示例(Circle 类)

 

class Circle { private: double radius; mutable int calcCount = 0; // mutable:const函数中可修改 public: double calculateArea() const { // const成员函数 calcCount++; // 合法:mutable变量不受const约束 // radius = 10; // 错误:不能修改非mutable成员 return PI * radius * radius; } void setRadius(double r) { // 非const成员函数 radius = r; } }; // 使用场景 const Circle c1(5.0); c1.calculateArea(); // 正确:const对象调用const函数 // c1.setRadius(6.0); // 错误:const对象不能调用非const函数 Circle c2(5.0); c2.calculateArea(); // 正确:非const对象可调用const函数 c2.setRadius(6.0); // 正确:非const对象调用非const函数 
补充:mutable 关键字(const 函数的例外)

mutable修饰的成员变量,可突破 const 函数的约束(用于统计、缓存等不影响对象核心状态的场景):

 

class Circle { private: mutable int calcCount = 0; // 可在const函数中修改 public: double calculateArea() const { calcCount++; // 合法:统计函数调用次数 return PI * radius * radius; } }; 

场景 7:const 修饰对象(const 对象)

语法

 

const 类名 对象名(构造参数); 
核心作用

对象只读:只能调用 const 成员函数,不能修改任何成员变量(包括非 const 成员)。

示例
const Circle c(5.0); // c.setRadius(6.0); // 错误:const对象不能调用非const函数 cout << c.calculateArea() << endl; // 正确:调用const函数 

三、核心规则与易错点

  1. const 是编译期约束:仅在编译阶段检查,若通过const_cast强制修改 const 变量,会导致 “未定义行为”(可能崩溃 / 数据异常):
  2. const 的顺序
    • 普通变量:const int aint const a 等价;
    • 指针:const int* pint const* p 等价(左数),int* const p(右指)不同;
  3. const 引用绑定临时值:临时值(如10、表达式结果)的生命周期会被 const 引用延长至引用生命周期结束;
  4. const 成员函数调用规则
    • const 成员函数 → 只能调用其他 const 成员函数(避免间接修改对象);
    • 非 const 成员函数 → 可调用 const / 非 const 成员函数。
const int num = 10; int* p = const_cast<int*>(&num); *p = 20; // 未定义行为!编译器可能优化num为常量折叠,num仍为10 

四、常量正确性(Const Correctness)规范

遵循以下规范,可大幅减少编程错误:

  1. 所有只读数据(如 PI)用const修饰;
  2. 所有不修改对象状态的成员函数加const
  3. 函数参数若无需修改,加const(尤其是自定义类型的引用 / 指针参数);
  4. const 对象仅调用 const 成员函数,非 const 对象按需调用;
  5. 静态常量成员加static const,减少内存开销。

总结

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk