//
// main.m
// 8_11_pm_内存
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou3g. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc]init]; // retainCount 是 1
p.name = @"曹操";
[p release]; //retainCount 应该减为 0;
//person对象已经被销毁,不能再通过指针操作。 只是标记删除,只有alloc时,才销毁。
// for (int i = 0; i < 1000; i ++) {
// NSLog(@"%@",p.name);
// }
/*
1、创建自动释放池对象
2、在自动释放池内,对 对象进行autorelease操作。
3、自动释放池会记录对象(如果同一个对象,两次调用autorelease,该对象会被记录两次)
4、当自动释放池销毁时,记录的所有对象,依次调用release方法
*/
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSLog(@"----%lu",pool.retainCount);
Person *p1 = [[Person alloc]init];
p1.name = @"刘备";
[p1 retain]; // 2
[p1 retain];
[p1 autorelease]; // 2
[p1 autorelease];
NSLog(@"%lu",p1.retainCount);
//销毁自动释放池
[pool release];
//release 与drain的区别在于,release把垃圾和垃圾桶都销毁了,drain只是把垃圾清除。
// [pool drain];
NSLog(@"%lu",p1.retainCount);
#pragma mark ----------自动释放池的第二种写法
//mrc两种都支持,arc只支持第二种
Person *p2 = [[Person alloc]init];
[p2 retain];
NSLog(@"%lu",p2.retainCount);
@autoreleasepool {
[p2 autorelease];
NSLog(@"-------%lu",p2.retainCount);
}
NSLog(@"-------%lu",p2.retainCount);
//pe指向的对象的引用计数为1
//如果只写一句[p2 release];对象正常销毁,不存在内存问题,
//如果不写[p2 release]; main函数运行结束后,局部变量pe被销毁,没有指针指向对象,造成内存泄露
//如果写了不止一次,那叫过度释放,本质是野指针异常。
[p2 release];
#pragma mark --------------内存之copy
Person *p3 = [[Person alloc]init];
p3.name = @"三弟";
p3.age = 18;
//p4指向拷贝后的新对象。
Person *p4 = [p3 copy];
NSLog(@"%@",p4.name);
NSLog(@"%lu",p4.age);
//深拷贝,浅拷贝
//深拷贝,拷贝的是对象,即创建了新的对象。
//person类实现的是深拷贝,Student实现的是浅拷贝
NSLog(@"%@",p4);
NSLog(@"%@",p3);
p3.release;
p4.release;
//浅拷贝,拷贝的是指针,拷贝的是原来的对象,没有创建新的对象。
Student *s = [[Student alloc]init];
Student *s1 =[s copy];
NSLog(@"%@",s);
NSLog(@"%@",s1);
//字符串的retainCount
//常量字符串的retainCount是最大值
#pragma mark ------------NSString的内存管理
//字符串是一个很特殊的类,有时在常量区,有时在堆区。
//内存管理只参考内存管理原则,即影响引用计数的5个方法。
//因为存储在常量区
NSString * str = @"张飞";
NSLog(@"%lu",str.retainCount);
NSString *str3 = [str copy];
NSLog(@"%lu",str3.retainCount);
NSString *str2 = [[NSString alloc]initWithFormat:@"德邦"];
NSLog(@"%lu",str2.retainCount);
//对常量区的进行release相当于没有进行操作
NSString *str4 = [[NSString alloc]initWithFormat:@"1"];
NSLog(@"%lu",str4.retainCount);
//NSString类型的对象,调用copy得到的结果
NSString *str5 = [[NSString alloc]initWithFormat:@"武松打虎"];
NSString *str6 = [str5 copy];
NSLog(@"%p",str5);
NSLog(@"%p",str6);
NSLog(@"%lu",str5.retainCount);
//copy与mutablecopy
//对象调用copy方法得到的是不可变的对象
//对象调用mutablecopy,得到的是可变的对象
NSArray *arr = @[@"1",@"2",@"3"];
NSMutableArray *muarr = [arr mutableCopy];
[muarr addObject:@"4"];
NSLog(@"%@",muarr);
}
return 0;
}
如果要想实现copy,必须遵守NSCopying 协议,还要改写copyWithZone方法。
//
// Person.h
// 8_11_oc内存管理
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou3g. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCopying>
{
NSString *_name;
NSInteger _age;
}
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign)NSInteger age;
@end
//
// Person.m
// 8_11_oc内存管理
//
// Created by lanou3g on 15/8/11.
// Copyright (c) 2015年 lanou3g. All rights reserved.
//
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"对象被销毁了,");
[super dealloc]; //写在dealloc方法实现的最后一句,后面不能再有代码。
}
-(id)copyWithZone:(NSZone *)zone
{
//以前的ios版本需要这样写,如果需要向下兼容(兼容低版本,可以这这句代码)
// Person *temp = [Person allocWithZone:zone];
Person *temp = [[Person alloc]init];
temp.name = self.name; //self表示调用copy方法的对象,即被拷贝的对象。
temp.age = self.age;
return temp;
}
@end