【iOS】static、extern、const、auto关键字以及联合使用

目录

    • 前言
      • extern关键字
      • static关键字
      • const关键字
    • 联合使用
      • static和extern
      • static和const
      • extern和const
    • auto关键字


先了解一下静态变量所在的全局/静态区的特点:【iOS】内存五大分区

前言

上面提到的全局/静态区中存放的是全局变量或静态变量:

全局变量是指变量值可以在运行时被动态修改
静态变量static修饰的变量,包含静态局部变量和静态全局变量

extern关键字

extern只能用来修饰全局变量,不能修饰其他变量,一般定义的全局变量默认带有extern,只不过被省略了,多用于跨文件引用

1. 与.h文件的关系

.h文件时为了更好地方便其他文件去调用本文件中的变量、属性和方法,作用同extern

如果在.h文件中声明全局变量,在OC中是不合法的,主要在@interface ExternModel : NSObject@end之间,当然如果在他们两个之外也是可以声明的:

在这里插入图片描述

应显式声明extern表明其不是成员变量,而是全局变量:

@interface ExternModel : NSObject
extern NSString* xyString;
@end

常见用法:

.h结合extern使用:如果在.h文件中声明了extern全局变量,那么在同一个类中的.m文件对全局变量的赋值必须时:数据类型+变量名(与声明时一致) = XXXXX,并且在调用时导入.h文件:

//  ExternModel.h
#import <Foundation/Foundation.h>
@interface ExternModel : NSObject
extern NSString* xyString;
@end//  ExternModel.m
#import "ExternModel.h"
@implementation ExternModel
NSString* xyString = @"Hello!!";
@end

例如,在viewController.mmain.m中调用,则可以引入ExternModel.h,否则无法识别全局变量

在这里插入图片描述

当然也可以通过不导入头文件的方式进行调用,通过extern调用,来获取全局变量的值

2. extern引用变量

如果在其他文件中访问一个类的全局变量,可以不用导入.h文件,通过extern去直接访问:

#import <Foundation/Foundation.h>
//#import "ExternModel.h"int main(int argc, const char * argv[]) {@autoreleasepool {//  只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量extern NSString* xyString;NSLog(@"%@", xyString);}return 0;
}
//  Hello!!

static关键字

static修饰变量后该变量就被定义成为一个静态变量

静态全局变量

static修饰全局变量,存储区仍在全局/静态区,但限定了该全局变量只能在当前源文件访问(从定义之处开始到文件结尾),限制了其作用域,在外部文件中是不可见的

好处: 定义后只会指向固定的指针地址,供当前文件使用,同一源程序的其他文件中可以使用相同名字的变量,不会发生冲突
不足: 存在的生命周期长,从定义直到程序结束
建议: 从内存优化和程序编译的角度来说,尽量少用全局静态变量,因为存在的生命周期长,一直占用空间。程序运行时会单独加载一次全局静态变量,过多的全局静态变量会造成程序启动慢

静态局部变量

static修饰局部变量,存储区由栈区变为静态区(.rwdata),延长了该局部变量的生命周期,虽然直到源程序结束该变量才会被销毁,但其作用域仍为局部,即当定义该变量的函数或者语句块结束时,就不可使用,尽管该变量仍存在

好处: 定义后只会存在一份值,只会初始化一次,每次调用都是使用的同一个对象内存地址的值,并没有重新创建,节省空间
不足: 存在的生命周期长,从定义直到程序结束
建议: 静态全局和局部变量从根本上没有什么区别,只是作用域不同而已。如果仅一个类中的对象和类方法使用并且值可变,可以定义全局静态变量

静态函数

在函数的返回类型前加上关键字static,函数就被定义成为静态函数

函数的实现和声明默认情况下是extern的,当函数被static修饰成为静态函数后,该函数的作用域仅限于定义它的源文件,同一程序的其他文件无法直接调用该函数,也无法通过外部链接访问

好处: 同一源程序的其他文件中可以使用相同名字的变函数,不会发生冲突;编译器可对static静态函数进行更多的优化,因为已知该函数不会在其他源文件中使用

const关键字

const是用来修饰常量(只读值)的,注意与宏的区别(EOC 2.0里面有提到《Effective Objective-C 2.0》读书笔记——熟悉Objective-C,良好的编码习惯提倡我们多用类型常量,少用#define类型常量):

在这里插入图片描述

宏的好处:宏能定义一些函数、方法;const不能
宏的坏处:使用大量宏,容易造成编译时间久每次都需要重新替换;宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误

const仅仅用来修饰右边的变量:

// 定义变量
int a = 1;
// 允许修改值
a = 20;
// const两种用法
// 1.const:修饰基本变量p
// 这两种写法是一样的,const只修饰右边的基本变量b
const int b = 20; // b:只读变量
int const b = 20; // b:只读变量
// 不允许修改值
b = 1;
// 2. const:修饰指针变量*p,带*的变量,就是指针变量
// 定义一个指向int类型的指针变量,指向a的地址
int *p = &a;
int c = 10;
// 允许修改p指向的地址
p = &c;
// 允许修改p访问内存空间的值
*p = 20;
// const修饰指针变量访问的内存空间,修饰的是右边*p1,
// 两种方式一样
const int *p1; // *p1:常量 p1:变量
int const *p1; // *p1:常量 p1:变量
// 允许修改p指向的地址
p1 = &a;
// 不允许修改p访问内存空间的值
*p1 = 27;
// const修饰指针变量p1
int * const p2; // *p1:变量 p1:常量
// 不允许修改p指向的地址
p2 = &a;
// 允许修改p访问内存空间的值
*p2 = 27;
// 第一个const修饰*p1 第二个const修饰 p1
// 两种方式一样
const int * const p3; // *p1:常量 p1:常量
int const * const p3; // *p1:常量 p1:常量
// p的指向和指向内存空间的值都不能修改
p3 = &a;
*p3 = 27;

在这里插入图片描述

联合使用

static和extern

extern引用变量时会先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找

static int age = 21;void test(void) {static int age = 21;age++;NSLog(@"%d", age);
}int main(void) {test();test();extern int age;NSLog(@"%d", age);return 0;
}
// 打印结果:
// 22
// 23
// 21

static和const

声明一个只读的静态变量,常用于声明上面《EOC 2.0》提到的类型常量

// 开发中经常将无需改变的key值作为类型(字符串)常量
static NSString* const key1 = @"keyValue1";
static NSString const * key2 = @"keyValue2";
static const NSString* key3 = @"keyValue3";

extern和const

声明一个全局的类型常量,供多个文件共享

全局常量正规写法:开发中便于管理所有的全局变量,通常搞一个GlobeConst文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找

// GlobeConst.h
extern NSString * const kGlobalConstKey;// GlobeConst.m
NSString * const kGlobalConst = @"globalConst";

auto关键字

认识了这么多修饰变量的关键字,最后再来简单认识一下之前未了解过的auto关键字

变量被auto修饰后,编译器会根据初始化表达式自动推断出变量的类型:

auto x = 3.14;      // x 是浮点型 double
auto y = 520;       // y 是整形 int
auto z = 'a';       // z 是字符型 char
auto nb;            // error,变量必须要初始化
auto double nbl;    // 语法错误, 不能修改数据类型   
auto pi = new auto(42); // pi 的类型被推导为 int*
const auto& y = x; // y 的类型被推导为 const int&

auto关键字更适用于类型冗长复杂、变量使用范围专一时,使程序更清晰易读。如:

 std::vector<int> vect; for (auto it = vect.begin(); it != vect.end(); ++it){  //it的类型是std::vector<int>::iteratorstd::cin >> *it;}

或者保存lambda表达式类型的变量声明:

  auto ptr = [](double x){return x*x;};//类型为std::function<double(double)>函数对象

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

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

相关文章

人工智能大模型发展的新形势及其省思

作者简介 肖仰华&#xff0c;复旦大学计算机科学技术学院教授、博导&#xff0c;上海市数据科学重点实验室主任。研究方向为知识图谱、知识工程、大数据管理与挖掘。主要著作有《图对称性理论及其在数据管理中的应用》、《知识图谱&#xff1a;概念与技术》&#xff08;合著&a…

C++基础语法:STL之容器(5)--序列容器中的list(二)

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 序列容器的学习.以<C Prime Plus> 6th Edition(以下称"本书")内容理解 本书中容器内容不多只有几页.最好是有数据结构方面的知识积累,如果没有在学的同时补上 接上一篇C基础语法:STL之容器…

excel系列(三) - 利用 easyexcel 快速实现 excel 文件导入导出

一、介绍 在上篇文章中&#xff0c;我们介绍了 easypoi 工具实现 excel 文件的导入导出。 本篇我们继续深入介绍另一款更优秀的 excel 工具库&#xff1a;easyexcel 。 二、easyexcel easyexcel 是阿里巴巴开源的一款 excel 解析工具&#xff0c;底层逻辑也是基于 apache p…

HTTPS 的加密过程 详解

HTTP 由于是明文传输&#xff0c;所以安全上存在以下三个风险&#xff1a; 窃听风险&#xff0c;比如通信链路上可以获取通信内容。篡改风险&#xff0c;比如通信内容被篡改。冒充风险&#xff0c;比如冒充网站。 HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议&#xff0c…

Spring Cloud LoadBalanced

负载均衡(Load Balance&#xff0c;简称 LB) 是⾼并发, ⾼可⽤系统必不可少的关键组件. 当服务流量增⼤时, 通常会采⽤增加机器的⽅式进⾏扩容, 负载均衡就是⽤来在多个机器或者其他资源中, 按照⼀定的规则合理分配负载. 负载均衡的⼀些实现 就像是eureka中对请求进行轮询的…

Java对象创建过程的解析

Java对象创建过程的解析 1. 类的加载与连接2. 内存分配2.1 分配方式2.2 本地线程缓冲分配&#xff08;TLAB&#xff09; 3. 初始化内存4. 设置对象头 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 对象的创建是一个涉及多个步骤的复杂过程…

Qt:26.Qt项目:贪吃蛇游戏

一、项目功能演示&#xff1a; 开始界面可以点击进入游戏。 点击进入游戏之后&#xff0c;切换到选项界面&#xff0c;该界面可以选择游戏难度&#xff0c;回退&#xff0c;以及查询最近一次游戏得分。 游戏具体界面如下。贴图啥的可以自己换&#xff0c;本人审美不咋行&#x…

[SUCTF 2019]EasySQL1

这是一个简单的SQL注入题&#xff0c;但是因为我的SQL基础约等于0&#xff0c;所以做起来很难。 首先试试引号是否被过滤 可以看到单引号、双引号都被过滤了&#xff0c;试试其他的盲注都不行&#xff0c;基本上可以确定不能用这种方法。 在测试的过程中发现&#xff0c;输入…

RICHTEK立锜科技 WIFI 7电源参考设计

什么是WIFI 7? WiFi 7&#xff08;Wi-Fi 7&#xff09;是下一代Wi-Fi标准&#xff0c;对应的是IEEE 802.11将发布新的修订标准IEEE 802.11be –极高吞吐量EHT&#xff08;Extremely High Throughput &#xff09;。Wi-Fi 7是在Wi-Fi 6的基础上引入了320MHz带宽、4096-QAM、Mu…

oceanbase架构、功能模块、数据存储、特性、sql流转层等概念详解

一、架构图 OceanBase 数据库采用无共享&#xff08;Shared-Nothing&#xff09;分布式集群架构&#xff0c;各个节点之间完全对等&#xff0c;每个节点都有自己的 SQL 引擎、存储引擎、事务引擎&#xff0c;运行在普通 PC 服务器组成的集群之上&#xff0c;具备高可扩展性、高…

【LabVIEW作业篇 - 4】:属性节点赋值和直接节点赋值的区别体现

文章目录 属性节点赋值和直接节点赋值的区别体现 属性节点赋值和直接节点赋值的区别体现 创建5个圆形指示灯&#xff0c;然后循环点亮&#xff0c;先给圆形指示灯赋值假变量&#xff0c;然后再进行循环。 运行结果&#xff0c;观察结果&#xff0c;发现刚开始运行时&#xff0…

引领小模型潮流!OpenAI发布功能强大且成本低的GPT-4o mini

GPT-4o mini的成本比GPT-3.5 Turbo低了超过60%&#xff0c;其聊天表现优于Google的Gemini Flash和Anthropic的Claude Haiku。该模型从周四开始对ChatGPT的免费用户、ChatGPT Plus用户和团队订阅用户开放&#xff0c;并将在下周向企业用户开放。OpenAI计划未来将图像、视频和音频…

【Leetcode】一、排序

文章目录 1、选择排序2、冒泡排序3、插入排序 1、选择排序 给定数组arr&#xff0c;其长度为n。实现思路&#xff1a; 遍历数组&#xff0c;从0 ~ n - 1&#xff0c;找到最小的&#xff0c;找到后&#xff0c;和数组的第一个元素互换位置继续新一轮遍历&#xff0c;从1 ~ n -…

路网双线合并单线——ArcGIS 解决方法

路网双线合并成单线是一个在地图制作、交通规划以及GIS分析中常见的需求。双线路网定义&#xff1a;具有不同流向、不同平面结构的道路。此外&#xff0c;车道数较多的道路&#xff08;例如&#xff0c;双黄实线车道数大于4的道路&#xff09;也可以视为双线路网&#xff0c;本…

扩容升级丨极海正式推出G32A1465系列汽车通用MCU,驱动智驾再进阶

继2023年推出G32A系列汽车通用平台首发产品G32A1445系列后&#xff0c;极海宣布正式推出G32A1465系列全新汽车通用MCU&#xff0c;以满足日益增长的智能驾驶应用需求。作为升级迭代产品&#xff0c;G32A1465专为应用范围不断扩大的高运算要求而设计&#xff0c;集成丰富的通信接…

数据结构(5.2_3)——二叉树的存储结构

二叉树的顺序存储 #define MAXLEN 255struct TreeNode {ElemType value;//结点中的数据元素bool isEmpty;//结点是否为空 };void main() {TreeNode t[MaxSize]; } 定义一个长度为MaxSize的数组t&#xff0c;按照从上至下、从左至右的顺序依次存储完全二叉树中的各个结点 几个…

前端组件化探索与实践:Vue自定义暂无数据组件的开发与应用

摘要 随着前端开发技术的不断进步&#xff0c;组件化开发已成为提升开发效率、降低维护成本的关键手段。本文旨在通过介绍一款Vue自定义暂无数据组件的开发与实践&#xff0c;深入探讨前端组件化开发的重要性、优势及其在实际项目中的应用。 一、引言 在前端开发中&#xff0…

七天打造一套量化交易系统-Day0-量化投资发展历程

七天打造一套量化交易系统-Day0-量化投资发展历程 1、本间宗久&#xff08;1724-1803&#xff09;2、朱尔斯雷格纳特 Jules Regnault&#xff08;1834—1894&#xff09;3、拉尔夫纳尔逊艾略特&#xff08;1871-1948&#xff09;4、爱德华索普(Edward O. Thorp)&#xff08;193…

windows中使用Jenkins打包,部署vue项目完整操作流程

文章目录 1. 下载和安装2. 使用1. 准备一个 新创建 或者 已有的 Vue项目2. git仓库3. 添加Jenkinsfile文件4. 成功示例 1. 下载和安装 网上有许多安装教程,简单罗列几个 Windows系统下Jenkins安装、配置和使用windows安装jenkins 2. 使用 在Jenkins已经安装的基础上,可以开始下…

Element UI DatePicker选择日期范围区间默认显示前一个月和本月

要求&#xff1a;点击el-date-picker选择时间范围时&#xff0c;默认展开当月和上个月。 但是Element UI的组件默认展开的是本月和下一个月&#xff0c;如下图所示&#xff1a; 改为 <span click"changeInitCalendarRange"><el-date-picker v-model"r…