java内存中的五大区域_五大内存区

一:五大内存区

说到内存分区,内存即指的是RAM。

栈区,堆区,全局区,常量区,代码区

634374e3d766

image.png

1、栈区:

创建临时变量时由编译器自动分配,在不需要的时候自动清除的变量的存储区。

里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

优点:

栈是系统数据结构,对应线程/进程是唯一的。

快速高效,缺点时有限制,数据不灵活。[先进后出]

栈空间分静态分配 和动态分配两种。

静态分配是编译器完成的,比如自动变量(auto)的分配。

动态分配由alloc函数完成。

栈的动态分配无需释放(是自动的),也就没有释放函数。

为可移植的程序起见,栈的动态分配操作是不被鼓励的!

@interface TestObject()

@end

@implementation TestObject

- (void)testMethodWithName:(NSString *)name

{

//方法参数name是一个指针,指向传入的参数指针所指向的对象内存地址。name是在栈中

//通过打印地址可以看出来,传入参数的对象内存地址与方法参数的对象内存地址是一样的。但是指针地址不一样。

NSLog(@"name指针地址:%p,name指针指向的对象内存地址:%p",&name,name);

//*person 是指针变量,在栈中, [Person new]是创建的对象,放在堆中。

//person指针指向了[Person new]所创建的对象。

//那么[Person new]所创建的对象的引用计数器就被+1了,此时[Person new]对象的retainCount为1

Person *person = [Person new];

}

2、堆区:

就是那些由 new alloc 创建的对象所分配的内存块,它们的释放系统不会主动去管,由我们的开发者去告诉系统什么时候释放这块内存(一个对象引用计数为0时系统就会回销毁该内存区域对象)。一般一个 new 就要对应一个 release。在ARC下编译器会自动在合适位置为OC对象添加release操作。会在当前线程Runloop退出或休眠时销毁这些对象,MRC则需程序员手动释放。堆可以动态地扩展和收缩。

注意:全局区又可分为未初始化全局区:bss段和初始化全局区:data段。

优点:

灵活方便,数据适应面广泛,但是效率有一定降低。[顺序随意]

堆是函数库内部数据结构,不一定唯一。

不同堆分配的内存无法互相操作。

堆空间的分配总是动态的

虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存,释放内存匹配是良好程序的基本要素。

//alloc是为Person对象分配内存,init是初始化Person对象。本质上跟[Person new]一样。

Person *person = [[Person alloc] init];

3、全局/静态存储区:

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

4、常量存储区:

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

5、代码区

存放函数的二进制代码。

NSString *string1;//string1 这个NSString 类型的指针,未初始化存在于的

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

static NSString *string3;//string3 这个NSString 类型的指针存在于的

static NSString *string4 = @"1234";//string4 这个NSString类型的指针存在与的,@“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类型的指针 存在于的

static NSString *str2 = @"4321"; //str2这个NSString类型的指针 存在于的

NSString *str3;//str3这个NSString类型的指针 存在于

str3 = [[NSString alloc]initWithString:@"1234"];//[[NSString alloc]initWithString:@"1234"]这个对象 存在于

}

二:static、extern、const比较

1、static静态变量

静态变量有两种

全局静态变量

优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会指向固定的指针地址,供所有对象使用,节省空间。

缺点:存在的生命周期长,从定义直到程序结束。

建议:从内存优化和程序编译的角度来说,尽量少用全局静态变量,因为存在的生命周期长,一直占用空间。程序运行时会单独加载一次全局静态变量,过多的全局静态变量会造成程序启动慢,当然就目前的手机处理器性能,几十几百个估计也影响不大吧。

局部静态变量

优点:定义后只会存在一份值,每次调用都是使用的同一个对象内存地址的值,并没有重新创建,节省空间,只能在该局部代码块中使用。

缺点:存在的生命周期长,从定义直到程序结束,只能在该局部代码块中使用。

建议:局部和全局静态变量从本根意义上没有什么区别,只是作用域不同而已。如果值仅一个类中的对象和类方法使用并且值可变,可以定义全局静态变量,如果是多个类使用并可变,建议值定义在model作为成员变量使用。如果是不可变值,建议使用宏定义

static NSString *name;

2、extern全局变量

全局变量有两种

对内的全局变量:没有用extern在.h中修饰的变量,仅定义在.m中让该变量只能在该类使用

优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会存一份值,供所有对象使用,节省空间。跟全局静态变量一样,只是少了static修饰少了static特性

缺点:存在的生命周期长,从定义直到程序结束

建议:跟全局静态变量都一样了,还需要用对内的全局变量吗?不用extern修饰就少了extern的特性,还不如用全局静态变量,至少能明确的知道static是对内使用的

外部全局变量:除了该类,其他文件也可以访问该变量

优点:除了该类,其他文件也可以访问该变量

缺点:存在的生命周期长,从定义直到程序结束。并且外部可以修改其值,出现错误不容易定位

建议:使用全局变量的原因就在于其对外的特性,但是其使用的方便性没有使用model的属性或宏来得方便。程序启动的时候会单独加载全局变量,同理与全局静态变量,少使用。

.m中要定义

NSString *name;

.h中同时要定义

extern NSString *name;

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

3、const常量

不同于变量,常量的值是固定不可变的,一般用于只读值。

优点:只可以读取值,不能修改。一般用于接口或者文字显示这种固定值。添加extern可以对外全局常量,任意位置都可以访问

缺点:存在的生命周期长,从定义直到程序结束。需要在.h .m中分别定义代码较多

建议:良好的编码习惯而言,少使用宏,多使用常量。因为常量声明是有明确类型的,而宏只是替换并不能进行类型判断。不够严谨。

.h中定义extern

extern NSString *const name;

.m中定义值

NSString *const name = @"123";

//const声明部位不同,意义也不同。const定义的是其右边整体不可变。

//*const name1定义的是 name1 不可变。 name1是指针。

//因此 不能通过修改name1而指向其他值。常规的const使用这个方法定义不可修改的值

NSString *const name1 = @"456";

//const * name定义的是 * name不可变, 而*name指向的是@"789",

//也就是说@"123"这个内存地址的值不可变为其他值。

NSString const * name2 = @"789";

//但name指针可以指向其他值,所以该定义方式无法保证值的唯一性。

NSString *newName = @"222";

name2 = newName;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值