您的位置:首页 > 大数据 > 人工智能

oc MRC内存管理机制alloc/retain/copy/release/autorelease

2015-08-27 09:13 357 查看
////////////////////////////////////////////////////////////////////////////////

main.m

//////////////////////////////////////////////////////////////////////////////

#import <Foundation/Foundation.h>

#import "Person.h"

#import "Person1.h"

#import "Student.h"

int main(int argc, const char * argv[]) {

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

[person retain];

@autoreleasepool {

Person *person=[[Person alloc]initWithName:@"bill" Age:23];

//在堆区开辟一块空间,存储创建好的person对象。

//对象的存储空间地址在person中。

//person指向创建的对象。

//通常,我们将指向某个对象的指针,代指对象。

Person *person2=person;

//person3也是一个指针,没有指向任何对象。

//nil 就是空。只能给指针赋值。

//在Oc中对nil的任何操作都是无效的。也就是空操作。

Person *person3=nil;

[person3 isEqualTo:person2];

#pragma mark ===== 内存管理机制 ========

//gar ==》ARC改为NO

//引用计数。--只开辟一个空间,所有的操作都是对这一个空间的操作。

//多个指针指向同一个对象。

//为了避免出现野指针,对象使用时,需要引用计数+1,释放对象时,引用计数-1。

#pragma mark ======= alloc ===========

//引用计数+1。

//0==》1的过程。

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

NSLog(@"palloc-alloc之后的:%lu",[palloc retainCount]);

#pragma mark ======= retain =============

//引用计数+1。

[palloc retain];

NSLog(@"palloc-retain之后:%lu",[palloc retainCount]);

//另外一个指针指向palloc,不会影响引用计数。

//单纯的指向是不会影响引用计数的,引用计数要改变必须是对这块地址有所操作。

Person *palloc2=palloc;

NSLog(@"%lu",palloc2.retainCount);

[palloc2 retain];

NSLog(@"%lu",palloc2.retainCount);

#pragma mark ====== release ===============

//引用计数-1。

NSLog(@"palloc没有release之前:%lu",[palloc retainCount]);

[palloc release];

NSLog(@"palloc用了release之后:%lu",[palloc retainCount]);

[palloc release];

NSLog(@"---%lu",[palloc retainCount]);

[palloc release];

// NSLog(@"==%lu",[palloc retainCount]);

#pragma mark ====== autorelease ==============

//在未来的某一时刻引用计数-1。

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

[Pautorelease retain];//2

[Pautorelease autorelease];//还是2,未来会-1.出了池子会-1.

NSLog(@"[[[%lu",[Pautorelease retainCount]);

[person retain];

[person autorelease];

NSLog(@"autorelease:池子里>>%lu",person.retainCount);

#pragma mark ======== copy ===============

//

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

NSLog(@"copy前:%lu",perCopy.retainCount);

Person *per4=[perCopy copy];

NSLog(@"copy后:%lu",per4.retainCount);

#pragma mark ======= Person1.h/.m =============

//创建释放池

NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];

Person1 *per1=[[Person1 alloc]init];//1

per1.name=@"hjki";

per1.age=13;

[per1 retain];//2

[per1 retain];//3

[per1 release];//2

[per1 autorelease];//暂时为2,放到栈中,出了释放池,从栈顶开始释放掉。===>这块地址的引用计数为1

NSLog(@"池子内部autorelease:%lu",[per1 retainCount]);

// [per1 autorelease];//===》变为0

// [per1 release];//过度释放。

//内存泄露:定义完,没有释放。

// NSLog(@">>%lu",[per1 retainCount]);

//销毁释放池

[pool release];

//自动释放池有两种格式,MRC下支持两种写法。

//在ARC下只支持@autoreleasepool{}写法。

NSLog(@"池子外面autorelease:%lu",[per1 retainCount]);

NSLog(@"%lu",[per1 retainCount]);

Person1 *per2=[[Person1 alloc]init];

per2.name=@"nmk";

per2.age=19;

[per2 retain];//引用计数:2

[per2 retain];//3

//per3指向新拷贝的对象。

Person1 *per3=[per2 copy];

NSLog(@"%@,%ld",per3.name,per3.age);

NSLog(@"深拷贝per2=>:%lu,per3=>:%lu",per2.retainCount,per3.retainCount);

NSLog(@"深拷贝拷贝的内容:%@,%ld",per3.name,per3.age);

//深拷贝,是拷贝地址的内容,即创建新的对象。

//拷贝的是内容,所以实质上没有对地址进行操作,所以,引用计数不改变。

//浅拷贝,拷贝的是指针,即操作的是原来的对象,没有创建新的对象。

NSLog(@"深拷贝后地址=》per2:%p,per3:%p",per2,per3);

#pragma mark ===== Student.h/.m ====================

Student *stu1=[[Student alloc]init];

stu1.name=@"bejin";

stu1.gender=@"male";

stu1.number=29;

[stu1 retain];

//浅拷贝==>拷贝的竟然是地址,是对同一块地址的操作。

//浅拷贝的时候,相当于是对该地址进行了操作。所以引用计数+1.

Student *stu2=[stu1 copy];

NSLog(@"stu2:%@,%@,%ld",stu2.name,stu2.gender,stu2.number);

NSLog(@"浅拷贝后的地址stu1=>:%p=====stu2=>:%p",stu1,stu2);

NSLog(@"浅拷贝stu1=>%lu,stu2=>%lu",stu1.retainCount,stu2.retainCount);

#pragma mark ========== NSString 内存 ========================

//指向的是常量区

NSString *str1=@"中国";

NSLog(@"str1引用计数:%lu",str1.retainCount);

//指向的是堆区

NSString *str2=[[NSString alloc]initWithFormat:@"中国北京"];

NSLog(@"str2引用计数;%lu",str2.retainCount);

NSLog(@"str2地址:%p",str2);

//下面这句竟然是浅拷贝。浅拷贝是对引用计数有影响,会使计数+1.至于为什么会这样,估计就只能自己没事猜测猜测底层代码了。

//本来,alloc是要开辟一个新地址的,由于在检测过程中,发现拷贝的是一个字符串,所以,就不必开辟新的了,之后,str4和str2就公用一个地址,所以属于浅拷贝,并且浅拷贝属于对地址的直接的操作,所以,引用计数要+1。

NSString *str4=[[NSString alloc]initWithString:str2];

NSLog(@"str4引用计数:%lu str2引用计数:%lu",str4.retainCount,str2.retainCount);

NSLog(@"str4地址:%p str2地址:%p",str4,str2);

//

NSString *str3=[[NSString alloc]initWithString:str1];

NSLog(@"str3引用计数:%lu,%lu",str3.retainCount,str1.retainCount);

}

NSLog(@"\nautorelease:池子外>>%lu",person.retainCount);

return 0;

}

//////////////////////////////////////////////////////////////////////////

Student.h

/////////////////////////////////////////////////////////////////////////

#import <Foundation/Foundation.h>

@interface Student : NSObject<NSCopying>

@property(nonatomic,retain) NSString *name;

@property(nonatomic,retain) NSString *gender;

@property(nonatomic,assign) NSInteger number;

@end

////////////////////////////////////////////////////////////////////////

Student.m

/////////////////////////////////////////////////////////////////////////

#import "Student.h"

@implementation Student

//浅拷贝的重写方法。

-(id)copyWithZone:(NSZone*)zone{

return [self retain];

}

@end

////////////////////////////////////////////////////////////////////////

Person1.h

/////////////////////////////////////////////////////////////////////////

#import <Foundation/Foundation.h>

@interface Person1 : NSObject<NSCopying>

@property(nonatomic,retain) NSString *name;

@property(nonatomic,assign) NSInteger age;

@end

///////////////////////////////////////////////////////////////////////////

Person1.m

///////////////////////////////////////////////////////////////////////////

#import "Person1.h"

@implementation Person1

//深拷贝的重写。

-(id)copyWithZone:(NSZone *)zone{

//原始的。如果需要兼容更低的版本,可以使用这句话。

// Person1 *p1=[[Person1 allocWithZone:zone]init];

//这是现在的。

Person1 *p1=[[Person1 alloc]init];

p1.name=self.name;

p1.age=self.age;

return p1;

}

//当对象的引用计数为0时,对象自动调用。

- (void)dealloc

{

NSLog(@"引用计数为零,对象自动调用。销毁对象%@,释放内存空间.",self);

[super dealloc];

}

@end

/////////////////////////////////////////////////////////////////////////////////

Person.h

/////////////////////////////////////////////////////////////////////////////////

#import <Foundation/Foundation.h>

@interface Person : NSObject<NSCopying>

@property NSString *name;

@property NSInteger age;

-(id)initWithName:(NSString*)name

Age:(NSInteger)age;

+(id)personName:(NSString*)name

Age:(NSInteger)age;

-(NSString *)description;

-(void)dealloc;

@end

////////////////////////////////////////////////////////////////////////////////

Person.m

///////////////////////////////////////////////////////////////////////////////////

#import "Person.h"

@implementation Person

//浅拷贝的重写。

- (id)copyWithZone:(NSZone *)zone{

return [self retain];

}

-(id)initWithName:(NSString*)name

Age:(NSInteger)age{

self=[super init];

if (self) {

_name=name;

_age=age;

}

return self;

}

+(id)personName:(NSString*)name

Age:(NSInteger)age{

Person *person=[[Person alloc]initWithName:name Age:age];

return person;

}

-(NSString *)description{

return [NSString stringWithFormat:@"%@,%ld",_name,_age];

}

-(void)dealloc{

[super dealloc];

NSLog(@"计数为0");

}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: