当前位置: 首页 > news >正文

C / C++ const 全面总结

在 C / C++ 中,const 关键字用于定义不可修改的变量,这些变量在声明后不能被改变。通过使用const 关键字,可以提高代码的可读性和安全性,防止意外修改变量的值。

下面是一些示例,演示如何使用 const 关键字:

1.定义常量

const int MAX_SIZE = 100;

这里,MAX_SIZE 是一个常量,其值在整个程序的生命周期中都不会改变。如果尝试修改它,编译器会报错。

2. 常量指针和指向常量的指针

常量指针指向常量的指针是不同的概念。下面是具体的代码示例:

指向常量的指针 (pointer to const)

一个指向常量的指针是一个指向常量对象的指针。通过这个指针不能修改所指向的对象。它的声明格式是 const 类型* 指针名

int x = 10;
const int* ptr = &x; // ptr 是一个指向常量 int 的指针// *ptr = 20; // 错误:不能通过 ptr 修改 x 的值
x = 20; // 直接修改 x 的值是允许的

在这个例子中,ptr 指向 x,但是不能通过 ptr 修改 x 的值。

自身是常量的指针 (const pointer)

int x = 10;
int y = 20;
int* const ptr = &x; // ptr 是一个常量指针,指向 int 类型*ptr = 30; // 允许:可以通过 ptr 修改 x 的值
// ptr = &y; // 错误:ptr 是常量指针,不能改变它指向的位置

在这个例子中,ptr 总是指向 x,可以通过 ptr 修改 x 的值,但不能让 ptr 指向 y

指向常量的引用 (reference to const)

一个指向常量的引用是一个引用常量对象的引用。通过这个引用不能修改所引用的对象。它的声明格式是 const 类型& 引用名

int x = 10;
const int& ref = x; // ref 是一个指向常量 int 的引用// ref = 20; // 错误:不能通过 ref 修改 x 的值
x = 20; // 直接修改 x 的值是允许的

在这个例子中,ref 引用了 x,但是不能通过 ref 修改 x 的值。(不能通过别名去改变本身,但是可以通过本身的名字去修改自身的名字)

总结

  • 指向常量的指针 (const 类型* 指针名): 不能通过指针修改所指对象,但指针自身可以指向不同对象。

  • 常量指针 (类型* const 指针名): 指针自身是常量,不能指向其他对象,但可以通过指针修改所指对象。

  • 指向常量的引用 (const 类型& 引用名): 不能通过引用修改所引用对象,但引用自身总是指向最初绑定的对象。

通过这些例子,可以更清晰地理解 const 关键字在指针和引用中的不同应用场景。

3. 在函数参数中使用 const

使用 const 指针参数

void printValue(const int* ptr) {// 不能通过 ptr 修改它所指向的值std::cout << *ptr << std::endl;
}

通过将函数参数定义为 const,可以防止在函数内部修改参数所指向的值,提高代码的安全性。

 使用 const 引用参数

void printValue(const int& value) {// 不能修改 value 的值std::cout << value << std::endl;
}

使用 const 引用参数,既避免了拷贝大对象的开销,又保证了参数不会在函数内部被修改。

4. 常量成员函数 

在类中,常量成员函数不会修改对象的状态。这样的函数在声明时需要使用 const 关键字:

class MyClass {
public:int getValue() const {return value;}private:int value;
};

这里,getValue 是一个常量成员函数,它保证不会修改 MyClass 对象的任何成员变量。

5. 常量对象 

class MyClass {
public:void display() const {std::cout << "Displaying value" << std::endl;}
};int main() {const MyClass obj;obj.display(); // 可以调用常量成员函数return 0;
}

这里,obj 是一个常量对象,只能调用常量成员函数,不能调用会修改对象状态的成员函数。

6. const 和 define 的区别? 

在C++中,使用const关键字和使用预处理指令#define来定义常量是两种不同的方法,它们具有一些关键的区别:

  1. 类型安全const 定义的常量具有明确的类型,可以进行类型检查。这有助于避免类型相关的错误。

  2. 作用域限制const 定义的常量有特定的作用域,通常是在它被声明的块中。这有助于避免命名冲突,并增加了代码的可维护性。

  3. 调试友好const 定义的常量在调试过程中可以被看到,因为它们是符号名称。

  4. 内存分配const 常量通常会分配存储空间(尽管编译器可能会优化),可以取地址。

示例

const int MAX_VALUE = 100;

使用 #define 定义常量
  1. 预处理器指令#define 是一个预处理器指令,用于在编译之前替换文本。它不进行类型检查,也没有数据类型。

  2. 全局替换#define 创建的宏在它被定义后的所有地方有效,直到被#undef指令取消或文件结束。

  3. 不占用存储空间:宏通常不分配存储空间,因为它们在编译前就被替换成相应的值或表达式。

  4. 可能导致意外的行为:由于文本替换的方式,#define 宏可能导致一些意外的行为,尤其是在复杂的表达式中。

示例

#define MAX_VALUE 100

区别总结
  • 类型安全const#define 提供更好的类型安全。

  • 作用域控制const 变量有特定的作用域,而 #define 没有作用域概念,它是全局替换。

  • 调试const 常量在调试时更容易追踪。

  • 内存分配const 可能会占用存储空间,而 #define 不会。

  • 编译器优化:现代编译器通常能够对 const 常量进行优化,尤其是在它们没有被取地址时。

因此,在C++中,通常推荐使用const来定义常量,因为它提供了更好的类型安全、作用域控制和调试能力。然而,在某些特殊情况下,例如当需要定义宏函数或进行条件编译时,#define 仍然非常有用。

什么时候用 const 、什么时候用 define ?
  • 使用 const:当你需要定义一个具有特定类型的不变值,并且这个值只在某个特定区域(比如一个函数或类中)有效时。例如,你想在一个函数中定义一个不会改变的整数或浮点数:

const int maxUsers = 100;
const double pi = 3.14159;
  • const 保证了类型安全(比如你不能不小心把字符串赋给一个整数类型的 const),并且让代码更容易理解和维护。

  • 使用 define:当你需要定义一个全局常量,或者需要创建一个宏(比如一个简单的代码片段)时。这种情况下,类型不是主要关注点,而且这个值或代码片段将在整个程序中有效。

#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))

 define 是在编译之前进行文本替换,所以它不关心类型安全,也不受作用域的限制。

总结:如果你需要类型安全和作用域控制,用 const。如果你需要全局替换或创建宏,用 define。在现代 C++ 中,一般推荐使用 const,因为它更安全、代码更清晰。

总结

const 关键字在 C++ 中有多种用途,可以提高代码的安全性和可读性。通过定义常量、常量指针、指向常量的指针、常量成员函数和常量对象,我们可以确保在需要保护数据不被修改的地方使用 const,从而减少代码中的错误和漏洞。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python Chardet介绍
  • YOLO与PyQt5结合-增加论文工作量-实现一个目标检测的UI界面
  • 以“程序员”为主题的餐馆:编织代码与味蕾的奇妙邂逅
  • vue组件中的数据传递(2)--子组件传父组件
  • 带有WebUI的cron替代品Dagu
  • 【JavaScript】LeetCode:6-10
  • 【网络安全】服务基础第一阶段——第八节:Windows系统管理基础---- Web服务与虚拟主机
  • 软件单元测试工程模版化
  • 英伟达最新论文解析:剪枝与知识蒸馏 —— 可穿戴AI时代即将到来
  • HarmonyOS ArkUI工程框架解析
  • PHP软件下载-安装-环境配置
  • Unet改进15:添加TripletAttention||减少冗余计算和同时存储访问
  • 如何安装Docker
  • 抽象代数精解【12】
  • C++预处理定义
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • angular2 简述
  • Django 博客开发教程 16 - 统计文章阅读量
  • Flex布局到底解决了什么问题
  • maven工程打包jar以及java jar命令的classpath使用
  • OSS Web直传 (文件图片)
  • Python实现BT种子转化为磁力链接【实战】
  • QQ浏览器x5内核的兼容性问题
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Redis 懒删除(lazy free)简史
  • VUE es6技巧写法(持续更新中~~~)
  • vue-cli在webpack的配置文件探究
  • Zepto.js源码学习之二
  • 百度小程序遇到的问题
  • 大整数乘法-表格法
  • 欢迎参加第二届中国游戏开发者大会
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 力扣(LeetCode)965
  • 前嗅ForeSpider采集配置界面介绍
  • 区块链共识机制优缺点对比都是什么
  • 如何用vue打造一个移动端音乐播放器
  • 数组大概知多少
  • 一、python与pycharm的安装
  • 因为阿里,他们成了“杭漂”
  • 用jquery写贪吃蛇
  • 用quicker-worker.js轻松跑一个大数据遍历
  • const的用法,特别是用在函数前面与后面的区别
  • 带你开发类似Pokemon Go的AR游戏
  • 扩展资源服务器解决oauth2 性能瓶颈
  • #### golang中【堆】的使用及底层 ####
  • #《AI中文版》V3 第 1 章 概述
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (2024.6.23)最新版MAVEN的安装和配置教程(超详细)
  • (3)nginx 配置(nginx.conf)
  • (6)添加vue-cookie
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (十六)一篇文章学会Java的常用API
  • (算法)Travel Information Center
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (游戏设计草稿) 《外卖员模拟器》 (3D 科幻 角色扮演 开放世界 AI VR)