技 术 文 章 / 超 人
变量:
组成
变量的作用就是存放标识值。变量由三部分组成,变量名,变量类型,变量值。举个简单的例子:“一个存放水的玻璃盒子叫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";
未完待续。。。