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

C++关键字之const、inline、static

C++ 关键字总结

1.const

  • const是 constant 的缩写,本意是不变的、不易改变的意思。
  • 在C++中用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数
  • 使用如下:
//修饰普通类型变量
const int a =7;
int b=a; //true
a=8;  //false
  • 修饰指针变量
//1.const修饰指针指向的内容,则内容为不可变量
const int *p=8;//2.const修饰指针,则指针为不可变量
int a=9;
int* const p=&a;
*p=9; //正确
int b=7;
p=&b; //错误,指针不可变,改变其地址不对//3.const修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量
int a=8;
const int * const p=&a;
  • const 参数传递和函数返回值
//1. A:值传递的 const 修饰传递,一般这种情况不需要 const 修饰,因为函数会自动产生临时变量复制实参值。
#include<iostream>
using namespace std;void Cpf(const int a)
{cout<<a;// ++a;  是错误的,a 不能被改变
}int main(void)
{Cpf(8);system("pause");return 0;
}//2. 当 const 参数为指针时,可以防止指针被意外篡改。
#include<iostream>
using namespace std;void Cpf(int *const a)
{cout<<*a<<" ";*a = 9;
}int main(void)
{int a = 8;Cpf(&a);cout<<a; // a 为 9system("pause");return 0;
}//3. 自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,
//因此我们采取 const 外加引用传递的方法,并且对于一般的 int、double 等内置类型,我们不采用引用的传递方式。
#include<iostream>
using namespace std;class Test
{
public:Test(){}Test(int _m):_cm(_m){}int get_cm()const{return _cm;}private:int _cm;
};void Cmf(const Test& _tt)
{cout<<_tt.get_cm();
}int main(void)
{Test t(8);Cmf(t);system("pause");return 0;
}
  • const 修饰函数的返回值
//1. const 修饰内置类型的返回值,修饰与不修饰返回值作用一样。
#include<iostream>
using namespace std;const int Cmf()
{return 1;
}int Cpf()
{return 0;
}int main(void)
{int _m = Cmf();int _n = Cpf();cout<<_m<<" "<<_n;system("pause");return 0;
}//2. const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。//3. const 修饰返回的指针或者引用,是否返回一个指向 const 的指针,取决于我们想让用户干什么。
  • const修饰类成员函数
//const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值
//如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为 const 成员函数。
#include<iostream>
using namespace std;class Test
{
public:Test(){}Test(int _m):_cm(_m){}int get_cm()const{return _cm;}private:int _cm;
};void Cmf(const Test& _tt)
{cout<<_tt.get_cm();
}int main(void)
{Test t(8);Cmf(t);system("pause");return 0;
}
//***************************************************
class Test
{
public:Test(int _m,int _t):_cm(_m),_ct(_t){}void Kf()const{++_cm; // 错误++_ct; // 正确}
private:int _cm;mutable int _ct;
};

2.inline

  • 引入inline关键字原因

    • 在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。
    • 栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
    • 在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题,如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。
  • 内联函数并不是一个增强性能的灵丹妙药。只有当函数非常短小的时候它才能得到我们想要的效果;但是,如果函数并不是很短而且在很多地方都被调用的话,那么将会使得可执行体的体积增大。

下面我们来看一个例子:

#include <stdio.h>inline const char *num_check(int v)
{return (v % 2 > 0) ? "奇" : "偶";
}int main(void)
{int i;for (i = 0; i < 100; i++)printf("%02d   %s\n", i, num_check(i));return 0;
}

3. static

  • 静态全局变量

    • 该变量在全局数据区分配内存
    • 未经初始化的静态全局变量会被成需自动初始化为0
    • 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的
    • 静态全局变量都在全局数据区分配内存,包括后边将要提到的静态局部变量。对于一个完整程序,在内存中的分布情况为:代码区//low address全局数据区堆区栈区//high address
    • 一般程序把新产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区。全局数据区的数据并不会因为函数的退出而释放空间。
      //示例1
      #include <iostream>
      using namespace std;
      void fn();  //声明函数
      static int n;  //声明静态全局变量
      int main()
      {n = 20;  //为n赋初值cout<<n<<endl;//输出n的值fn();  //调用fn函数
      }
      void fn()
      {n++;  //n的值自加一(n=n+1)cout<<n<<endl; //输出n的值
      }
      
  • 静态全局变量和全局静态变量的区别

    • 1)全局变量是不显视用static修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern 全局变量名的声明,就可以使用全局变量。
    • 2)全局静态变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。
//示例2
//File1.c第一个代码文件的代码
#include <iostream>
using namespace std;
void fn();  //声明fn函数
static int n;  //定义静态全局变量
int main()
{n = 20;cout<<n<<endl;fn();
}
//File2.c第二个代码文件的代码
#include <iostream>
using namespace std;
extern int n;
void fn()
{n++;cout<<n<<endl;
}

编译并运行Example 2,您就会发现上述代码可以分别通过编译,但运行时出现错误。试着将
static int n; //定义静态全局变量
改为
int n; //定义全局变量
再次编译运行程序,细心体会全局变量和静态全局变量的区别。

  • 静态局部变量

    • 该变量在全局数据区分配内存;
    • 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
    • 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
    • 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;
//示例3
#include <iostream>
using namespace std;
void fn();
int main()
{fn();fn();fn();return 0;
}
void fn()
{static int n = 10;cout<<n<<endl;n++;
}
  • 静态函数

    • 静态函数不能被其他文件所用
    • 其他文件中可以定义相同名字的函数,不会发生冲突
  • 面向对象(类)中的静态属性使用

      1. 静态数据成员
      • 1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
      • 2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
      • 3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
      • 4)静态数据成员既可以通过对象名引用,也可以通过类名引用。
      1. 静态成员函数
      • 1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
      • 2)非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
      • 3)静态成员函数主要用来方位静态数据成员而不能访问非静态成员。

再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。

#include <stdio.h>
#include <string.h>
const int MAX_NAME_SIZE = 30;  class Student  
{  
public:  Student(char *pszName);~Student();
public:static void PrintfAllStudents();
private:  char    m_name[MAX_NAME_SIZE];  Student *next;Student *prev;static Student *m_head;
};  Student::Student(char *pszName)
{  strcpy(this->m_name, pszName);//建立双向链表,新数据从链表头部插入。this->next = m_head;this->prev = NULL;if (m_head != NULL)m_head->prev = this;m_head = this;  
}  Student::~Student ()//析构过程就是节点的脱离过程  
{  if (this == m_head) //该节点就是头节点。{m_head = this->next;}else{this->prev->next = this->next;this->next->prev = this->prev;}
}  void Student::PrintfAllStudents()
{for (Student *p = m_head; p != NULL; p = p->next)printf("%s\n", p->m_name);
}Student* Student::m_head = NULL;  void main()  
{   Student studentA("AAA");Student studentB("BBB");Student studentC("CCC");Student studentD("DDD");Student student("MoreWindows");Student::PrintfAllStudents();
}

程序将输出:
在这里插入图片描述

相关文章:

C++关键字之const、inline、static

C 关键字总结 1.const const是 constant 的缩写&#xff0c;本意是不变的、不易改变的意思。在C中用来修饰内置类型变量&#xff0c;自定义对象&#xff0c;成员函数&#xff0c;返回值&#xff0c;函数参数使用如下&#xff1a; //修饰普通类型变量 const int a 7; int ba;…...

【成为架构师课程系列】怎样进行概念架构(Conceptual Architecture)?

目录 前言 什么是概念架构 概念架构阶段的3个步骤 初步设计 高层分割 分层式概念服务架构 Layer:逻辑层 Tier: 物理层 按通用性分层 技术堆叠 考虑非功能需求 【禅与计算机程序设计艺术&#xff1a;更多阅读】 前言 胜兵先胜而后求战&#xff0c;败兵先站而后求胜。…...

PostgreSQL的下载安装教程(macOS、Windows)

postgresql是GIS服务端几乎不可避免要打交道的数据库。因为mysql的空间扩展真是不尽人意。所以想要学会GIS服务端知识,postgresql(下文简称pg)你是必须要会的。 首先要知道,pg是一个空间数据库,和普通数据库不同的是pg支持空间数据的存储与操作。这里所谓的空间数据一般指…...

98年的确实卷,公司新来的卷王,我们这帮老油条真干不过.....

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;前段时间我们公司来了个00后&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 …...

软件架构知识2-系统复杂度

架构设计的真正目的&#xff1a;是为了解决软件系统复杂度带来的问题&#xff0c;一个解决方案。 系统复杂度&#xff0c;如何入手&#xff1a; 1、通过熟悉和理解需求&#xff0c;识别系统复杂性所在的地方&#xff0c;然后针对这些复杂点进行架构设计。 2、架构设计并不是要…...

JavaSE学习day4_02 数组(超级重点)

3.数组 3.1什么是数组 数组就是存储数据长度固定的容器&#xff0c;存储多个数据的数据类型要一致。 3.2数组定义格式 3.2.1第一种&#xff08;常用&#xff09; 数据类型[] 数组名 示例&#xff1a; int[] arr; double[] arr; char[] arr; 3.2.2第二种(在…...

Theano教程:Python的内存管理

在写大型程序时候的一大挑战是如何保证最少的内存使用率。但是在Python中的内存管理是比较简单的。Python显示分配内存&#xff0c;使用引用计数系统管理对象&#xff0c;当指向某一个对象的引用数变为 0 的时候&#xff0c;该对象所占的内存就会被释放。理论上听起来很不错&am…...

Linux | Liunx安装Tomcat(Ubuntu版)

目录 一、下载并上传Tomcat压缩包到Ubuntu 1.1 下载并解压 1.2 执行 startup.sh 文件 二、验证Tomcat启动是否成功 2.1 查看启动日志 2.2 查看启动进程 三、Windows访问 Tomcat 服务 四、停止 Tomcat 服务 Tomcat是一款Web服务器&#xff0c;开发Web项目基本上都会用到…...

缓冲区浅析

缓冲区 程序运行输入数据时&#xff0c;从键盘的输入先存储到缓冲区&#xff0c;只有当缓冲区满或者输入回车时程序才会真正地从缓冲区读入数据 int main() {int a, b;cin >> a >> b;return 0; }in: 1 2\n 例如这里输入空格时程序没有输出&#xff0c;而是将空格…...

Day888.MySQL是怎么保证主备一致的 -MySQL实战

MySQL是怎么保证主备一致的 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于MySQL是怎么保证主备一致的内容。 MySQL 能够成为现下最流行的开源数据库&#xff0c;binlog 功不可没。 在最开始&#xff0c;MySQL 是以容易学习和方便的高可用架构&#xff0c;被开发人…...

互联网舆情监测系统的发展阶段,TOOM互联网舆情监测系统有哪些?

互联网舆情监测系统是一种利用计算机技术对互联网上的大量信息进行实时监测、分析和评估的工具&#xff0c;旨在了解公众对某一事件、话题或品牌等的态度、情感倾向和影响力等。通过对社交媒体、论坛、新闻媒体等多个渠道的数据采集和处理&#xff0c;系统能够实现舆情事件的追…...

GIT命令操作大全

文章目录一、前言二、工作模块2.1 Workspace&#xff1a;工作区2.2 Index / Stage&#xff1a;暂存区2.3 Repository&#xff1a;本地仓库2.4Remote&#xff1a;远程仓库三、GIT基本配置四、GIT项目代码管理4.1 初始化git仓库4.2 提交到暂存区(stage)4.3 将暂存区的文件恢复到工…...

突破传统开发模式,亚马逊云科技助力中科院加速推动合成生物学

当数字技术成为整个社会运行的底座&#xff0c;生物科学也能借力云计算从诸多繁琐重复的工作中解放出来&#xff0c;专注于生物设计与创新。来看看亚马逊云科技如何与TIBCAS合作&#xff0c;推动合成生物学的发展。 明确核心需求&#xff0c;选择合作伙伴 TIBCAS选择与亚马逊…...

分享开放通达信l2接口的过程,开发之后怎么使用?

随着互联网的不断进步&#xff0c;信息技术的不断发展&#xff0c;通达信l2接口技术逐步成熟。那么&#xff0c;这些开放通达信l2接口开发的过程是怎么样的呢?期间又会遇到什么问题&#xff0c;开放之后又会怎么使用呢&#xff1f;这篇文章带你深入了解。 通达信l2接口不像一…...

33、基于51单片机老人防跌倒蜂鸣器报警系统加速度检测

背景技术 老年人出门由于身体不灵活、视力较差&#xff0c;容易发生跌倒&#xff0c;现用的老年人跌倒报警装置是通过无线对讲系统研发的&#xff0c;它外观精美&#xff0c;自动化程度高&#xff0c;有很强的专业性&#xff0c;但是&#xff0c;设计者忽略了一个问题&#xf…...

【项目】基于SpringBoot+Freemarker+Mybatis+MySQL+LayUI实现CRM智能办公系统

这里写目录标题CRM基本概念CRM分类模块功能描述项目代码application-dev.yml部分页面代码CRM基本概念 圈内存在这么一句话&#xff1a;“世上本来没有 CRM&#xff0c;大家的生意越来越难做了&#xff0c;才有了 CRM。” 在同质化竞争时代&#xff0c;顾客资产尤为重要&#x…...

手写识别字体的步骤是什么?怎么识别图片中的文字?

手写识别字体的步骤是什么&#xff1f;怎么识别图片中的文字&#xff1f; 1. 打开信风工具网&#xff0c;点击拍照按钮&#xff0c;选择拍图识字模式&#xff0c;对准需要识别的文件进行拍摄&#xff61;在线工具地址&#xff1a; https://ocr.bytedance.zj.cn/image/ImageT…...

Mysql 存储过程

什么是存储过程&#xff1f; 存储过程是事先经过编译并存储在数据库的一段sql语句的集合 如何创建一个存储过程&#xff1f; create procedure 存储过程名称([参数列表]) beginsql语句; end#例 create procedure p1() beginselect * from t_goods;select * from t_user; end如…...

【LeetCode】每日一题(3)

目录 题目&#xff1a;1234. 替换子串得到平衡字符串 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;1234. 替换子串得到平衡…...

websocket学习

1.什么是websocket 1&#xff09;首先websocket和http一样&#xff0c;是一种网络通信协议&#xff0c;来自HTML5的特性&#xff1b; 2&#xff09;他可以使客户端和服务端进行双工通信&#xff0c;简单来说&#xff0c;就是双向通信&#xff1a;比如我们熟悉的http协议&…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...