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
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
相关文章推荐
- Syntax error, type annotations are available only when source level is at least 1.8
- install ftp client on kail
- Container With Most Water
- LightOJ 1403 - Air Raid【二分匹配】
- Leetcode: Contains Duplicate
- Leetcode: Factorial Trailing Zeroes
- ideaiu的使用
- CCComponentContainer,CCComponent解析
- 安装APK:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
- 异常:org.hibernate.HibernateException: 'hibernate.dialect' must be set when no Connection available
- Codeforces Round #317 [AimFund Thanks-Round] (Div. 1) B. Minimization 贪心 dp
- LeetCode题解:Factorial Trailing Zeroes
- HDU2473 - Junk-Mail Filter 利用虚拟数组实现删除并查集的节点
- 【图论】【最小生成树】[IOI2003]maintain
- [捉虫记录]关于Cascade Training Error的bug
- failure during conversion to COFF: file invalid or corrupt
- 【HDOJ 1021】 Fibonacci Again (矩阵快速幂(裸))
- HDOJ 2674 N!Again(找规律)
- 人工智能进入股市操盘获利巨大激荡股市
- See You Again