P12 C++静态关键字static

目录

01 前言

02 静态变量static

03 extern关键字

04 静态函数

最后的话


01 前言

static 关键字在 C++ 中有两个意思,这个取决于上下文。

第一种情况是在类或结构体外部使用 static 关键字,另一种是在类或者结构体内部使用 static。

  1. 类外面的 static 意味着你声明为 static 的内容,将只是在内部链接,这意味着它只能对它所在的翻译单元可见。
  2. 类或结构体内部的静态变量 static 意味着该变量将与类的所有实例共享内存,这意味着该静态变量在你的类创建的所有实例中,静态变量只有一个实例。类似的事情也适用于类中的静态方法。

本期不讨论静态 static 在类或结构体范围内的实际含义,只关注在类和结构体外部的 static。类内部的static放在下一期讨论

02 静态变量static

static int s_data = 15;

我在一个完全空的 C++ 文件中定义了一个静态变量,使用惯例使用 S_ 来表示这个变量是静态的,将其值设置为 5。它整体上看起来和其他变量是一样的,只不过在它前面的是 static 关键字,这意味着这个变量只会在当前这个转换单元内部链接。

静态变量或函数意味着当需要将这些函数或变量与实际定义的符号链接时,链接器不会在这个转换单元的作用域之外的地方寻找那个符号定义。

我们拿实际的代码来解释一下。

在第一个例子中21.1.cpp,我们创建了一个静态变量s_data,并将它设为 15,然后去另一个 C++ 文件21.cpp,也就是另一个转换单元,一个带有main函数空白 C++ 文件。在这里创建一个全局变量。将它与之前静态变量设置一样的名字。其值设置为十,打印这个变量。

运行之后,我们可以看到,程序是可以编译的,不会遇到任何问题。

然后我们回到 21.1.cpp 文件,删除了static 关键字。再次编译刚刚的代码。你会发现当它进入链接状态阶段时,会报一个链接错误。因为这个 s_data 变量已经在另一个转换单元中定义过了,当然是这样的,我们不能有两个同名的全局变量。

03 extern关键字

那么只有这一种调整方法了吗?当然不是。

我们可以这样修改。

  

这样操作意味着它会在外部转换单元中寻找 s_data 变量。这被称为 external linkage 或者 external linking。

现在运行代码也是没有问题了的。它可以输出 15,它引用了另外一个文件中的 s_data 变量的值。

这个时候如果我再次将另外一个文件中的 s_data标记为静态。——这个过程有点像在类中声明一个私有变量,链接器在全局作用域下将不会看到这个变量。程序它还是会报错,因为我们已经做了有效的标记,这个变量已经是私有的了。

04 静态函数

接下来我们试一下函数 function。

我在 21.cpp 文件中定义一个 function函 数。然后在 21.1.cpp 中也定义一个具有相同签名的函数,返回值也是 void。

编译一下这个程序。我们在链接阶段同样得到一个重复的符号错误。

回到 Static.cpp 文件中,使用 static 将它标记为静态的。链接器开始工作时,根本不会看到这个静态的函数。程序会顺利编译,不会得到任何错误。

 这就是 C++ 中静态的全部含义。

当你在类和结构体之外使用静态时,它只是意味着你声明的静态函数或静态变量只会在它所在的文件中被看到。

如果你想在头文件中声明一个静态变量,将头文件包含在两个不同的 C++ 文件中。其实和上面的例子是一样的,都是在两个转换单元中都声明了相同的 s_data 变量为静态变量。当然,当你包含那个头文件时,它会复制所有内容并将其粘贴在 C++ 文件中。也就是将一个静态变量放到两个不同的转换单元中,这个你要留意一下。

#include <iostream>extern int s_data;void funtion()
{}int main()
{std::cout <<s_data << std::endl;return 0;
}

最后的话

那么我们使用 static 的理由是什么呢?

你可以参考一下我们为什么要在类中使用 private?

如果你不需要变量是全局变量,你就需要尽可能多的使用静态变量。一旦在全局作用域下声明了东西,如果没有设定为static,链接器将会跨编译单元进行链接。这意味着你已经创建了一个完全全局的变量,它可以在任何地方使用,这可能会导致一些非常糟糕的 bug。

归根到底,全局变量是不好的。我不太喜欢用全局变量,也不建议你使用。除非你真的需要他们跨转换单元链接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/169722.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023.11.25更新关于mac开发APP(flutter)的笔记与整理(实机开发一)

我自己写的笔记很杂&#xff0c;下面的笔记是我在chatgpt4的帮助下完成的&#xff0c;希望可以帮到正在踩坑mac开发APP&#xff08;flutter&#xff09;的小伙伴 目标&#xff1a;通过MAC电脑使用flutter框架开发一款适用于苹果手机的一个APP应用 本博客的阅读顺序是&#xf…

SELinux零知识学习三十、SELinux策略语言之角色和用户(1)

接前一篇文章:SELinux零知识学习二十九、SELinux策略语言之类型强制(14) 三、SELinux策略语言之类型强制 SELinux提供了一种依赖于类型强制(类型增强,TE)的基于角色的访问控制(Role-Based Access Control),角色用于组域类型和限制域类型与用户之间的关系,SELinux中的…

列车停车控制算法及仿真研究

摘要 精确停车是列车自动驾驶系统的关键技术之一&#xff0c;其精度通常要求在30厘米之内。精确停车能保证列车交通系统的高效率运行。若列车停站不准确&#xff0c;不仅影响乘客的上下车&#xff0c;而且会造成列车晚点等诸多问题。因此&#xff0c;研究列车精确停车算法具有重…

[Docker]十.Docker Swarm讲解

一.Dokcer Swarm集群介绍 1.Dokcer Swarm 简介 Docker Swarm 是 Docker 公司推出的用来管理 docker 集群的工具&#xff0c; 使用 Docker Swarm 可以快速方便的实现 高可用集群 ,Docker Compose 只能编排单节点上的容器, Docker Swarm 可以让我们在单一主机上操作来完成对 整…

C语言—二维数组

一、二维数组的创建 int arr[3][4];char arr[3][5];double arr[2][4]; 数组创建&#xff1a;“[ ]”中要给一个常量&#xff0c;不能使用变量 二、二维数组的初始化 int arr[3][4]{1,2,3,4};int arr[3][4]{{1,2},{4,5}};int arr[][4]{{2,3},{4,5}}; 前面的为行&#xff0c…

【Unity入门】Input.GetAxis(““)控制物体移动、旋转

使用Unity的Input.GetAxis(“”)控制物体移动、旋转 Input.GetAxis(“”) 是 Unity 引擎中的一个方法&#xff0c;用于获取游戏玩家在 键盘 或 游戏手柄 上输入的某个轴&#xff08;Axis&#xff09;的值。这里的 “” 是一个字符串参数&#xff0c;表示要获取的轴的名称。 在…

01.让自己习惯C++

让自己习惯C 条款1&#xff1a;视C为一个语言联邦 条款1中提到了将C看作为一个“语言联邦”的概念。具体来说&#xff0c;“语言联邦”是指将C看作由多种不同的子语言组成的联邦。每种子语言都有自己的惯用法、工具和库&#xff0c;可以用来解决特定的问题。因此&#xff0c;…

『亚马逊云科技产品测评』活动征文|低成本搭建物联网服务器thingsboard

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 0. 环境 - ubuntu22&#xff08;注意4G内存勉强够&#xff0c;部署完…

『Postman入门万字长文』| 从工具简介、环境部署、脚本应用、Collections使用到接口自动化测试详细过程

『Postman入门万字长文』| 从工具简介、环境部署、脚本应用、Collections使用到接口自动化测试详细过程 1 Postman工具简介2 Postman安装3 Postman界面说明4 一个简单请求4.1 请求示例4.2 请求过程 5 Postman其他操作5.1 import5.2 History5.3 Environment5.4 Global5.5 其他变…

使用信息面板沟通研发工作

凌鲨里面的内容面板里面有专门针对研发团队的白板功能&#xff0c;它可以把文档&#xff0c;图片&#xff0c;软件设计&#xff0c;需求&#xff0c;任务/缺陷等相关研发要素串接起来。 使用 你还可以调整背景颜色。 引用项目内数据 点击面板中的连接会在右侧打开对应内容

不要再往下翻了,你要的女宝穿搭我都有哦

分享女儿的睡衣穿搭 清新自然的浪漫紫 一眼就击中了我的心巴 软糯亲肤上身体验感超赞 轻松自在无束缚 防风又保暖&#xff0c;居家外出都可哦

SpringBoot实现文件批量打包下载

实现将指定的多个文件打包成一个压缩文件下载。 1. 引入pom依赖 <dependencies><!-- Spring Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency&…

Angular中的getter函数

Angular 中的 getter 函数每次被调用时会返回一个新对象时&#xff0c;这些新对象并不使用同一个堆内存。详细解释一下&#xff1a; Getter 函数的作用是获取某个属性的值。在 Angular 中&#xff0c;getter 函数通常用于获取响应式数据&#xff08;例如 Observables 或 Signal…

基于C#实现Kruskal算法

这篇我们看看第二种生成树的 Kruskal 算法&#xff0c;这个算法的魅力在于我们可以打一下算法和数据结构的组合拳&#xff0c;很有意思的。 一、思想 若存在 M{0,1,2,3,4,5}这样 6 个节点&#xff0c;我们知道 Prim 算法构建生成树是从”顶点”这个角度来思考的&#xff0c;然…

# Panda3d 碰撞检测系统介绍

Panda3d 碰撞检测系统介绍 文章目录 Panda3d 碰撞检测系统介绍碰撞几何体的介绍碰撞球体碰撞胶囊反碰撞球体碰撞平面碰撞多边形碰撞射线碰撞直线碰撞段碰撞抛物线碰撞长方体碰撞系统图碰撞处理器碰撞处理器队列碰撞处理器事件碰撞处理器回退模型(CollisionHandlerPusher)物理…

ArkTS基础知识 【习题】

判断题 1.循环渲染ForEach可以从数据源中迭代获取数据&#xff0c;并为每个数组项创建相应的组件。 正确(True) 2. Link变量不能在组件内部进行初始化。 正确(True) 单选题 1.用哪一种装饰器修饰的struct表示该结构体具有组件化能力&#xff1f;(A) A. Component B. Entry C…

c语言内存管理

通常程序访问的是虚拟内存&#xff0c;虚拟内存映射到物理内存的一小部分。 在Linux系统中&#xff0c;虚拟内存默认为4G的大小。每个进程都有独立的4G内存地址空间。 int main() {char s[] "hello world"; //s数组位于栈区&#xff0c;复制了一份字符串到数组里ch…

【设计模式-2.1】创建型——单例模式

说明&#xff1a;设计模式根据用途分为创建型、结构性和行为型。创建型模式主要用于描述如何创建对象&#xff0c;本文介绍创建型中的单例模式。 饿汉式单例 单例模式是比较常见的一种设计模式&#xff0c;旨在确保对象的唯一性&#xff0c;什么时候去使用这个对象都是同一个…

MySQL 批量插入记录报 Error 1390 (HY000)

文章目录 1.背景2.问题3.分批插入4.一次最多能插入多少条记录&#xff1f;参考文献 1.背景 Golang 后台服务使用 GORM 实现与 MySQL 的交互&#xff0c;在实现一个通过 Excel 导入数据的接口时&#xff0c;使用 Save 方法一次性插入大量记录&#xff08;>1w&#xff09;时报…

springsecurity6配置四

一、springsecurity自定义过滤url配置 package com.school.information.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;import java.util.List;/*** 需要放行的…