iOS-变量从认识到理解

技 术 文 章 / 超 人


变量:

  • 组成
    变量的作用就是存放标识值。变量由三部分组成,变量名,变量类型,变量值。举个简单的例子:“一个存放水的玻璃盒子叫X玻璃水盒”,存放水,意味着盒子中拥有的东西就是水即变量的值,而这个值是有特性的,根据它的特性而区分类型的即是变量类型,水不能放在纸盒子和木盒子中,因为会漏水,所以放在玻璃盒子中,因为玻璃盒子能完美的存放水,选择玻璃盒子的原因是因为值是水,值的特性决定了存放值的变量类型。而X玻璃水盒是这个盒子的名字即变量名,用四个字X玻璃水盒去形容或者说称呼它比用“一个存放水的玻璃盒子”要简洁方便而且更加针对性。变量名就是为了从文字和称呼上区分理解它的类型与值,规范的变量名要能体现变量值的意义和变量类型。
    例如:存放用户名的变量 NSString *userNameString = @“用户名”;
    变量值特性决定了变量的类型,变量名体现了变量值与变量类型的特性`

  • 指针(变量)
    指针中包含类型,指针地址,指针变量。
    例子:int a = 10; NSString * str = @“1234”;
    类型:a变量的类型是int类型,因为它没有 * 是基本数据类型。str指针的类型是指针类型,因为有*表示是指针
    指针地址:是储存指针或者变量所在内存中的地址,仅仅代表变量或者指针本身,而不能代表它们所指向的值。可以用&来获取指针地址,用%p来打印值,例如:NSString *string = @“123”;NSLog(@“%p”,&string);打印结果是0xea544280;打印出来的就是string的指针地址,它代表的仅仅是string这个变量名或者说指针。 跟“123”这个值无关。
    指针变量:是存储所在内存中的地址的一个可变量,把指针变量拆分为指针和变量,指针表示指针变量所储存的是一个指针地址,变量表示指针变量所存储的地址会发生改变,即指针变量中所储存的是变量值在内存中的地址,例如刚刚说所的@“123”。这个值是有单独的内存地址的。而变量中的指针变量就是记录这个值的地址。

NSString *string = @"123";
NSLog(@"指针变量的地址:%p",string);
NSLog(@"指针地址:%p",&string);
string = @"321";
NSLog(@"指针变量的地址:%p",string);
NSLog(@"指针地址:%p",&string);
string = @“123”;
NSLog(@"指针变量的地址:%p",string);
NSLog(@"指针地址:%p",&string);

打印结果

指针变量的地址:0x108767218
指针地址:0x7ffee7498b78
指针变量的地址:0x108767278
指针地址:0x7ffee7498b78
指针变量的地址:0x108767218
指针地址:0x7ffee7498b78

由此可以发现, 指针地址一直没有变,因为我们一直使用的都是string这个指针。而当改变string这个指针所指向的值时,string的指针变量地址就发生了改变。因为值不同了,值所在内存中的地址就不同了。具体原因呢就要说到栈区,堆区,全局区,文字常量区,代码区。


栈区,堆区,全局区,常量区,代码区,自由存储区(内存分析上说)

  • 栈区
    就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区
    里面的变量通常是局部变量函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

  • 堆区
    就是那些由 new 分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个 new 就要对应一个 delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。ARC下系统已经很好的帮助管理了。
    堆可以动态地扩展和收缩。

  • 自由存储区
    就是那些由 malloc 等分配的内存块,他和堆是十分相似的,不过它是用 free 来结束自己的生命的。

  • 全局/静态存储区
    全局变量静态变量被分配到同一块内存中,在以前的 C 语言中,全局变量又分为初始化的和未初始化的(初始化的全局变量和静态变量在一块区域,
    未初始化的全局变量与静态变量在相邻的另一块区域,
    同时未被初始化的对象存储区可以通过 void* 来访问和操纵,
    程序结束后由系统自行释放),在 C++ 里面没有这个区分了,
    他们共同占用同一块内存区。

  • 常量存储区
    这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。一般值都是放在这个地方的

NSString *string1;//string1 这个NSString 类型的指针,未初始化存在于<全局区>的<BBS区>

NSString *string2 = @"1234";//string2 这个NSString类型的指针,已初始化存在与<全局区>的<data数据区>,@“1234”存在与堆区,因为@代表了对象。 

static NSString *string3;//string3 这个NSString 类型的指针存在于<全局区>的<BBS区>

static NSString *string4 = @"1234";//string4 这个NSString类型的指针存在与<全局区>的<data数据区>,@“1234”存在与堆区,因为@代表了对象。stiring2和string4的值地址是一样的

static const NSString *string5 = @"654321";//const 修饰后  string5不能修改值。 其他的与string4一样

- (void)test
{
int  a;//a这个int类型的变量 是存在与<栈区>的
a = 10;//10这个值是存在与 <常量区>的

NSStirng *str;//str这个NSString类型的指针 存在于<栈区>
str = @“1234”;//@“1234”这个@对象存在于 <堆区>

static NSString *str1;//str1这个NSString类型的指针 存在于<全局区>的<BBS区>
static NSString *str2 = @"4321';//str2这个NSString类型的指针 存在于<全局区>的<data区>

NSString *str3;//str3这个NSString类型的指针 存在于<栈区>
str3 = [[NSString alloc]initWithString:@"1234"];//[[NSString alloc]initWithString:@"1234"]这个对象 存在于<堆区>

}

static静态变量

静态变量有两种

  • 全局静态变量
    优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会指向固定的指针地址,供所有对象使用,节省空间。
    缺点:存在的生命周期长,从定义直到程序结束。
    建议:从内存优化和程序编译的角度来说,尽量少用全局静态变量,因为存在的声明周期长,一直占用空间。程序运行时会单独加载一次全局静态变量,过多的全局静态变量会造成程序启动慢,当然就目前的手机处理器性能,几十几百个估计也影响不大吧。
  • 局部静态变量
    优点:定义后只会存在一份值,每次调用都是使用的同一个对象内存地址的值,并没有重新创建,节省空间,只能在该局部代码块中使用。
    缺点:存在的生命周期长,从定义直到程序结束,只能在该局部代码块中使用。
    建议:局部和全局静态变量从本根意义上没有什么区别,只是作用域不同而已。如果值仅一个类中的对象和类方法使用并且值可变,可以定义全局静态变量,如果是多个类使用并可变,建议值定义在model作为成员变量使用。如果是不可变值,建议使用宏定义
static NSString *name;

extern全局变量
全局变量有两种

  • 对内的全局变量:没有用extern在.h中修饰的变量,仅定义在.m中让该变量只能在该类使用
    优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会存一份值,供所有对象使用,节省空间。跟全局静态变量一样,只是少了static修饰少了static特性
    缺点:存在的生命周期长,从定义直到程序结束
    建议:跟全局静态变量都一样了,还需要用对内的全局变量吗?不用extern修饰就少了extern的特性,还不如用全局静态变量,至少能明确的知道static是对内使用的
  • 外部全局变量:除了该类,其他文件也可以访问该变量
    优点:除了该类,其他文件也可以访问该变量
    缺点:存在的生命周期长,从定义直到程序结束。并且外部可以修改其值,出现错误不容易定位
    建议:使用全局变量的原因就在于其对外的特性,但是其使用的方便性没有使用model的属性或宏来得方便。程序启动的时候会单独加载全局变量,同理与全局静态变量,少使用。
.m中要定义
NSString *name;

.h中同时要定义
extern NSString *name;

全局静态变量与全局变量 其实本质上是没有区别的,只是存在修饰区别,一个static让其只能内部使用,一个extern让其可以外部使用


const常量
不同于变量,常量的值是固定不可变的,一般用于只读值。
优点:只可以读取值,不能修改。一般用于接口或者文字显示这种固定值。添加extern可以对外全局常量,任意位置都可以访问
缺点:存在的生命周期长,从定义直到程序结束。需要在.h .m中分别定义代码较多
建议:看个人习惯吧,使用宏或者常量只是编译加载方式不一样而已

.h中定义extern
extern NSString *const name;
.m中定义值
NSString *const name = @"123";

未完待续。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,326评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,228评论 1 304
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,979评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,489评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,894评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,900评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,075评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,803评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,565评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,778评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,255评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,582评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,254评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,151评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,952评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,035评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,839评论 2 277