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

【学习笔记】C++ 中 static 关键字的作用

目录

  • 前言
  • static 作用在变量上
    • static 作用在全局变量上
    • static 作用在局部变量上
    • static 作用在成员变量上
  • static 作用在函数上
    • static 作用在函数上
    • static 作用在成员函数上

前言

在 C/C++ 中,关键字 static 在不同的应用场景下,有不同的作用,这里总结一下,避免在使用时弄混。

我按照以下的逻辑来分类 static 的作用场景

  1. static 作用在变量上
    1. static 作用在全局变量上:限制全局变量在本文件上
    2. static 作用在局部变量上:即使离开变量作用域,也保存变量值,比如用作计数器
    3. static 作用在成员变量上 :对象间共享该变量
  2. static 作用在函数上
    1. static 作用在函数上:函数可见性限制在本文件中(即使函数被声明在头文件,引用该头文件的其他 cpp 文件也无法使用该函数)
    2. static 作用在成员函数

static 作用在变量上

static 作用在全局变量上

对于普通的全局变量来说,同一项目中的其他文件也可访问相同的全局变量,若为了限制全局变量在本文件中,则需要在这个全局变量上加一个 static,这样该变量就只能在本文件可见。

我们先来演示一下,如何在一个文件中使用另一个文件的全局变量。

假设有 a.cppb.cpp,我们在 b 中定义一个全局变量 staticValue,然后在 a 中打印出来。

// b.cpp
// 全局变量
int staticValue = 10;void staticMain() {// ...
}
// a.cpp
#include <iostream>
using namespace std;// 必须通过 extern 关键字在整个项目搜索 staticValue
extern int staticValue;int main()
{cout << "在 a.cpp 中可见:" << staticValue << endl; // 在 a.cpp 中可见:10
}

显然我们成功在 a 文件中使用到了 b 文件内定义的全局变量。

现在,我希望将 staticValue 的全局可见性,限制在 b 文件内,不让其他文件也可以访问,于是我在 b 的 staticValue 前加上 static 关键字

// b.cpp
// 全局变量
static int staticValue = 10;void staticMain() {// ...
}

将代码如上修改后,当我们再次运行时,程序会在链接阶段报错,报错信息如下,根据描述可见在 aobj 文件(汇编后生成的对象文件)里没有解析到 staticValue 这个变量,达到了我们限制全局变量在本文件内的目的
在这里插入图片描述

static 作用在局部变量上

static 作用在局部变量上,即使离开变量作用域,也保存变量值,比如用作计数器。效果如下面的代码所示

可以看到,num 的值是逐渐累加的过程

#include <stdio.h>void count();int main(void)
{int i=0;for (i = 0;i <= 5;i++){count();}return 0;
}
void count()
{/*声明一个静态局部变量*/static int num = 0;num++;printf("%d\n",num); // 1 2 3 4 5 6
}

static 作用在成员变量上

在这种情况下,static 标记的变量可以在多个对象之间共享该变量,在底层上,因为 static 标记的变量并非存在于对象的内存空间,而是存在于数据区中(这涉及到 C 语言的内存布局)。

具体的效果如下面代码所示,我们声明了 3 个学生对象,分别是 zhangsan,lisi 和 wangwu,并在定义他们的时候给他们传入了各自的初始分数,最终求得三个人的总分。

#include <iostream>
using namespace std;class student {
private:static int sumScore;int myScore;
public:student(int m):myScore(m){sumScore += myScore;}int getSumScore() {return sumScore;}
};int student::sumScore = 0; // 静态成员变量必须在类外被初始化int main()
{student zhangsan(10);student lisi(20);student wangwu(30);cout << wangwu.getSumScore() << endl; // 60return 0;
}

关于 static 在修饰成员变量时的注意事项

  1. static 修饰的成员变量属于类,在对象间共享,因此某个对象修改了该变量,对其他对象也是可见的
  2. 静态成员变量的初始化必须要在类外,如上面的代码所示
  3. 静态成员变量的内存分配是发生在类外初始化的时候,而不是类或者对象创建的时候
  4. 静态成员变量可以通过类,也可以通过对象来访问,但必须遵守访问可见性(publicprivateprotected

static 作用在函数上

static 作用在函数上

它起到的效果和 static 作用在全局变量上类似,将函数的可见性限制在本文件内。

这里我们直接举被 static 修饰的函数的例子。

假设在 b.cpp 中我们定义了一个 bMain() 的函数,在 b.h 的头文件中进行声明,在 a.cpp 中引入这个头文件,并调用 bMain(),那么是可以正常调用的。

现在,我们在 b.cpp 中,在 bMain() 前加上一个 static 关键字,那么 a.cpp 就不能在调用了。

// b.cpp
#include <iostream>
using namespace std;static void bMain() {cout << "bMain" << endl;
}
// b.hpp
void bMain();
// a.cpp
#include "b.hpp"int main()
{bMain();return 0;
}

执行上述代码,我们可以看到和 “static 作用在全局变量上” 小节类似的报错问题
在这里插入图片描述

static 作用在成员函数上

静态成员函数具有和静态成员变量类似的性质和作用,一般可以用这种方式来确定类创建了多少个对象

  1. 静态成员函数在对象之间共享,或者说它独立于对象之外
  2. 可以通过对象来调用静态成员函数,也可以通过类名来调用静态成员函数
  3. 静态成员函数可以访问静态成员变量或其他静态成员函数,但不能使用当前对象指针
#include <iostream>
using namespace std;class student {
private:static int sumObj;
public:student() {sumObj += 1;}static int getObjNum() {return sumObj;}
};int student::sumObj = 0; // 静态成员变量必须在类外被初始化int main()
{student zhangsan;student lisi;student wangwu;cout << "student 有几个对象? " << student::getObjNum() << endl; // 3return 0;
}

可以看到,最终我们输出了 3 个对象

相关文章:

【学习笔记】C++ 中 static 关键字的作用

目录 前言static 作用在变量上static 作用在全局变量上static 作用在局部变量上static 作用在成员变量上 static 作用在函数上static 作用在函数上static 作用在成员函数上 前言 在 C/C 中&#xff0c;关键字 static 在不同的应用场景下&#xff0c;有不同的作用&#xff0c;这…...

攻防世界-web-file_include

1. 题目描述 打开界面&#xff0c;如下代码&#xff1a; 代码很简单&#xff0c;从参数中获取到filename然后include这个filename 2. 思路分析 2.1 首先参考常见做法&#xff0c;将参数设置为php://filter/readconvert.base64-encode/resourceflag.php&#xff0c;看是否有…...

C语言的函数指针、指针函数, 函数数组

函数指针 是指向函数的指针&#xff0c;它允许您在程序运行时动态选择要调用的函数。函数指针可以像普通变量一样传递、存储和使用&#xff0c;这使得它们在许多编程场景中非常有用&#xff0c;如回调函数、函数表、插件架构等。 以下是一个简单的例子来说明函数指针的概念&a…...

笔记本开启WiFi

笔记本开启WiFi 为了节省流量&#xff1a;笔记本开启WiFi 条件 支持热点的电脑&#xff1b;我的是华硕飞行堡垒7。 注意事项 笔记本连接公司网络&#xff0c;公司网络通常都在监管下的&#xff0c;手机连接wifi后&#xff0c;刷抖音、购物网站&#xff0c;公司后台会捕获你…...

力扣第37天----第322题、第279题

力扣第37天----第322题、第279题 文章目录 力扣第37天----第322题、第279题一、第322题--零钱兑换二、第279题--组合总和 Ⅳ 一、第322题–零钱兑换 ​ 整体思路&#xff0c;跟前面的几道完全背包差不多&#xff0c;就不具体解释了。有一些细节要注意&#xff0c;见代码注释。…...

【ArcGIS Pro二次开发】(67):处理面要素空洞

这个一个简单的小功能。 有些面要素可能会存在空洞&#xff0c;这个工具的目的就是获取面要素的空洞&#xff0c;或者去除空洞获取要素的边界。 这个功能其实在之前做拓扑功能的时候就已经有了&#xff0c;这次只是单独把它提取出来。因为有时候会单独用到这个功能。 一、要实…...

FPGA-结合协议时序实现UART收发器(一):UART协议、架构规划、框图

FPGA-结合协议时序实现UART收发器&#xff08;一&#xff09;&#xff1a;UART协议、架构规划、框图 记录FPGA的UART学习笔记&#xff0c;以及一些细节处理&#xff0c;主要参考奇哥fpga学习资料。 本次UART主要采用计数器方法实现&#xff0c;实现uart的稳定性发送和接收功能…...

web请求cookie中expires总结

用意 cookie 有失效日期 "expires"&#xff0c;如果还没有过失效期&#xff0c;即使重新启动电脑&#xff0c;cookie 仍然不会丢失 注意&#xff1a;如果没有指定 expires 值&#xff0c;那么在关闭浏览器时&#xff0c;cookie 即失效。 设置 如果cookie存储时间大…...

如何学习Java核心知识

Java作为一门广泛应用于软件开发的编程语言&#xff0c;拥有着强大的生态系统和丰富的资源&#xff0c;是值得投入时间和精力去学习的。以下是一些建议&#xff0c;帮助你系统地学习Java核心知识。 1. 学习Java语言基础&#xff1a; 学习Java语言基础是学习Java的第一步&…...

【AWS】如何用SSH连接aws上的EC2实例(虚拟机)?

目录 0.环境 1.连接结果示例 2.SSH连接思路 3.具体步骤 1&#xff09;安装并运行ssh服务 2&#xff09;启动ssh服务 3&#xff09;在AWS上找到正在运行的EC2实例&#xff0c;并且根据提供的ssh连接语句进行连接 0.环境 windows 11 64位 前提&#xff1a; 有aws账户&…...

数据结构——看完这篇保证你学会队列

数据结构——队列 一、队列的概念二、队列的实现方式三、队列所需要的接口四、接口的详细实现4.1初始化4.2销毁4.3入队4.5出队4.6获取队头元素4.7获取队尾元素4.8获取队列元素个数4.9判空 五、完整代码5.1Queue.h5.2Queue.c5.3test.c 一、队列的概念 队列&#xff1a;只允许在…...

开源免费缺陷管理工具:对比6款

在软件开发环境中&#xff0c;缺陷管理工具是关键的基础设施。例如&#xff0c;在构建一个电商平台时&#xff0c;这些工具能系统地跟踪从发现到解决的各个问题阶段。它们支持多用户协作&#xff0c;实现信息和状态的实时共享。通过数据分析&#xff0c;这些工具还能帮助团队识…...

Weblogic反序列化漏洞

文章目录 1、搭建环境2、漏洞特征3、漏洞利用1)获取用户名密码2)后台上传shell 4、检测工具 1、搭建环境 漏洞环境基于vulhub搭建–进入weak_password的docker环境 sudo docker-compose up -d拉取靶场 2、漏洞特征 404特征Weblogic常用端口&#xff1a;7001 3、漏洞利用…...

element-ui el-table 滚动到底部,进行加载下一页

使用element-ui 自带的InfiniteScroll 无限滚动组件无法使用在table里面&#xff0c;所以项目只能组件写一个 俺的方法是写了一个自定义组件&#xff0c;进行监听滚动条是否拉到最底部进行一个处理。方法如下 直接复制完事了&#xff0c; loadTableMore: { bind(el, binding…...

线性代数的学习和整理19,特征值,特征向量,以及引入的正交化矩阵概念(草稿)

目录 1 什么是特征值和特征向量&#xff1f; 1.1 特征值和特征向量这2个概念先放后 1.2 直观定义 1.3 严格定义 2 如何求特征值和特征向量 2.1 方法1&#xff1a;结合图形看&#xff0c;直观方法求 2.1.1 单位矩阵的特征值和特征向量 2.1.2 旋转矩阵 2.2 根据严格定义…...

初步了解android如何锁键

百年三万六千日&#xff0c;光阴只有瞬息间。 手机下面的三个图形&#xff0c;正方形&#xff0c;园形&#xff0c;三角形分别的什么建&#xff1f;都起到什么功能&#xff1f; 三角形的那个叫返回键&#xff0c;就是可以返回你的上一个操作; 圆形是HOME键&#xff0c;按一下可…...

行业追踪,2023-09-13

自动复盘 2023-09-13 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…...

$nextTick和setTimeout区别(宏任务微任务)

nextTick 在vue 源码中是利用 Promise.resolve()实现的。该问题实际就是Promise与setTimeout的区别&#xff0c;本质是Event Loop中微任务与宏任务的区别。 nextTick:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM。…...

Linux内核及可加载内核模块编程

图1 Linux系统整体结构 图2 Linux的源代码结构 下面显示一段内核模块代码案例&#xff1a; #include <linux/moduLe.h> #include <linux/kernel.h #include <linux/intt.h> /*模块的初始化函数lkp_ init()_init是用于初始化的修饰符 */ static int __init lk…...

软件设计师_备考笔记

考试介绍及考点分布情况 考试要求&#xff1a; &#xff08;1&#xff09;掌握数据表示、算术和逻辑运算&#xff1b; &#xff08;2&#xff09;掌握相关的应用数学、离散数学的基础知识&#xff1b; &#xff08;3&#xff09;掌握计算机体系结构以及各主要部件的性能和基…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...