当前位置: 首页 > 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协议&…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...