1、一个对象的创建的过程:
[[类 alloc]init];
1、先分配内存空间,存储对象
2、初始化成员变量
3、返回对象的指针地址
对象在创建的同时,内部会自动创建一个引用计数器,这个引用计数器是系统用来判断对象回收的唯一依据。当引用计数器为retainCount = 0时,系统会自动调用dealloc函数,将对象销毁。
[对象 retain]; // retainCount + 1
[对象 release]; //retainCount - 1
2、内存管理的原则:
只要出现了new alloc retain就一定要有对应的 release autorelease 出现。
3、手动内存管理研究的主要问题:
1、野指针操作:是指该指针指向的内存空间已经不存在了,该指针也没有赋值为 nil,对该指针继续进行操作。
2、内存泄漏:不再使用的对象一直存在内存中。
4、避免野指针操作的方法:
内存空间释放完毕之后的指针一定要赋值为 nil
5、避免内存泄漏的操作方法:
遵守内存管理的配对原则。
例子:
.h文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)run;
@end
.m文件
#import "Person.h"
@implementation Person
//该函数在对象接到release消息时由系统自动调用的
-(void)dealloc
{
//在对象自身被销毁之前,一定要先调用[super dealloc]释放父类中的相关对象
[super dealloc];
NSLog(@"Person 被销毁了");
}
- (void)run
{
NSLog(@"人跑起来了");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// 1
Person * p = [[Person alloc] init];
NSLog(@"%lu",p.retainCount);
// 2
[p retain];
NSLog(@"%lu",p.retainCount);
// 1
[p release];
NSLog(@"%lu",p.retainCount);
//0
[p release];
p = nil;
}
6、set方法的内存管理分析
car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
@property int speed;
- (void)run;
@end
Car.m
#import "Car.h"
@implementation Car
- (void)dealloc
{
[super dealloc];
NSLog(@"Car 被销毁了 %d速度",_speed);
}
- (void)run
{
NSLog(@"汽车跑起来了");
}
@end
Person.h
#import <Foundation/Foundation.h>
#import "Car.h"
@interface Person : NSObject
{
Car * _car;
NSString * _name;
}
- (void)setName:(NSString *)name;
- (NSString *)name;
- (void)setCar:(Car *)car;
- (Car *)car;
- (void)drive;
@end
Person.m
#import "Person.h"
//配对原则:new alloc retain 对应一个release,autorelease
@implementation Person
- (void)setName:(NSString *)name
{
if (_name != name)
{
[_name release];
_name = [name retain];
}
}
- (NSString *)name
{
return _name;
}
//面试笔试,出题率非常高
- (void)setCar:(Car *)car
{
if (_car != car)
{
[_car release]; //第一个Car对象进入是执行[nil release];
_car = [car retain];
}
}
- (Car *)car
{
return _car;
}
- (void)drive
{
[_car run];
}
- (void)dealloc
{
//目的是要保证在p对象存在的时候,car对象一定存在
[_car release];
[_name release];
[super dealloc];
NSLog(@"Person 被销毁了");
}
@end
7、@property参数的内存管理分析
7.1、@property 的3个作用:
- 生成set与get方法的声明
- 生成set与get方法的简单实现
- 如果没有相对应的成员变量,会自动生成_开头的成员变量
7.2、@property参数分为4类
1、与set方法内存管理相关的参数
retain:要生成符合内存管理原则的set方法(应用于对象)
@property (nonatomic,retain) Car* car;
assign: 直接赋值(对象类型,基本数据类型)
@property (nonatomic,assign) int age;
copy:拷贝
2、多线程相关
nonatomic:不生成多线程管理代码,(效率高)
@property (nonatomic ,retain) NSString * name;
atomic:生成多线程管理代码(不写默认就是这种方式)
实际开发中都用nonatomic
3、是否要生成set与get方法
readwrite:可读可写属性,同时生成set和get方法
readonly:只读属性,只生成get方法
@property (nonatomic,assign,readonly)int idCard;
4、set与get方法名称相关的参数
setter:设置生成的setter方法名称
getter:设置生成的get方法名称
@property (nonatomic,assign,setter = isDeid:,getter = isDeid)BOOL isDeid;
注意:
如果一个对象被生成了成员变量或者使用了@property生成了符合setter的内存管理方法,那么在dealloc函数对应一次release的操作。