内存管理
2015-07-26 21:17
302 查看
——————————————————————————————
1-对象所有权:
某个变量对指定的对象有使用权
2-引用计数
用来标识一个对象有几个使用者
3-引用计数器
记录使用者的个数的变量
变量类型 unsigned long
方法 retainCount
打印引用计数器的值 %lu
4-引用计数器的作用
作为对象是否要回收的依据
如果为0
要回收
如果>0
不要回收
5-对引用计数器的操作
向对象
发送 retain 消息 [obj retain];
使得对象的引用计数器+1
向对象
发送 release 消息
使得对象的引用计数器-1
6-对象回收注意:
一个对象如果回收的时候,系统自动的调用这个对象的 dealloc
方法
MRC - 手动内存管理
ARC - 自动引用计数管理 (默认的)
——————————————————————————————
//创建一个实例对象
Person *p = [Person
new];
//Person *p = [[Person alloc]init];
//对象引用计数器的值?
//[p retainCount];
可以获得对象的引用计数器的值
//对象创建完成后,默认的有一个所有者,就是他自己
NSUInteger n = [p
retainCount];
[p
retain]; //
让引用计数期的值+1
NSLog(@"n = %lu",n);
// 1
//release
可以让对象的引用计数器的值 -1
//如果对象的引用计数器的值
为 0
//那么此时这个对象会被立即回收
//会调用对象的 dealloc
方法(系统自动调用)
[p
release];
//0
//
//NSLog(@"p.retainCount = %lu",[p retainCount]); //
[p
release];
———————————内存管理的原则———————————————————
只要对象的引用计数不为0 ,这个对象就不能释放
使用某个对象之前,先retain
使用之后
然后 relase
口诀:
1)谁创建,谁释放
Person *p = [Person new];
Person *p1 = p;
[p release]; //谁创建谁release
2)谁retain
谁 release
Person *p = [Person new];
Person *p1 = p;
[p1 retain]; //谁retain
谁release
[p1 release];
[p release]; //谁创建谁release
野指针: 1)指针变量没有赋值 2)指向的空间已经不可用了
空指针:
谁都不指向
内存泄露:
申请的空间,没有及时的释放
——————————————————————————————
内存泄露: 申请了空间,到程序结束,你都没有任何释放空间的操作
单个对象的内存泄露问题
1) 创建了对象以后,没有释放
2) retain和release的个数不匹配问题
3) 对象使用的过程中赋值了nil
4) 在对象方法中不当的使用 retain
——————————————————————————————
set方法的内存管理问题:
1)对于基本数据类型的实例变量
int _age,float _height;
-(void)setAge:(int)age{
_age = age;
}
2) 对于对象类型的set方法,应该按照如下去写
Car *_car;
-(void)setCar:(Car *)car{
if(_car!=car){
[_car release];
_car = [car retain];
}
}
-(void)dealloc{
[_car release];
[super dealloc];
}
*/
——————————————————————————@perperty 参数————
1) 什么时候使用 assign?
基本数据类型的时候 int float double char
BOOL struct enum
2) 什么时候使用retain
如果实例变量是 OC对象类型的时候,要使用 retain
如果使用了retain
注意:
在 dealloc 方法,中要 release一次
——————————————————————————————
/*
assign 直接赋值
set方法没有使用retain
-(void)setDog:(Dog *)dog{
_dog = dog;
}
retain release旧的值,retain新的值
-(void)setDog:(Dog *)dog{
if(_dog != dog){
[ _dog release];
_dog = [dog retain];
}
}
——————————————————————————————
@property 参数分为三组
1) 原子性
atomic(默认) -
线程安全
nonatomic - 线程不安全(如果程序中没有使用多线程,建议使用这个)
2) 读写控制
readwrite(默认) -
生成get和set方法
readonly - 生成get方法
3) set内存管理
assign(默认) retain copy
——————————————————————————————
typedef struct T{
int hour;
int min;
int sec;
}Time;
//定义日期的结构体
typedef struct D{
//定义年月日
int year;
int month;
int day;
//定义时间
Time t;
}MyDate;
——————————————————————————————
@class 使用注意:
@class 用在.h文件中
用来告诉编译器这是一个类,这个类有哪些属性和行为,不会去立即检查
.m中如果使用 @class引入的这个类的属性和方法,都需要重新导入一次
这个类的头文件
——————————————————————————————
高
栈:
局部变量
堆:
动态申请的空间 对象
BSS: 没有初始化的全局变量和静态变量
数据区:已经初始化的全局变量和静态变量,字符串常量
代码区:程序编译后的代码的数据
低
//0x7fff5fbff7fc
int a = 10;
// 局部变量
//0x100000f82
char *s = "abc";
//字符串,数据区
NSLog(@"a addr = %p",&a);
//高地址
NSLog(@"s addr = %p",s);
//低地址
//0x100001070
NSString *str1 = @"abc";
//@"abc" 字符串常量 ,在常量区
NSString *str2 = [NSString
stringWithString:@"def"];
NSString *str3 = [[NSString
alloc] initWithString:@"abc"];
//0x100602420
//堆区
NSString *str4 = [NSString
stringWithFormat:@"aaa"];
NSString *str5 = [NSString
stringWithFormat:@"aaa"];
NSString *str6 = [[NSString
alloc] initWithFormat:@"bbbb"];
NSString *str7 = [[NSString
alloc] init];
[str7
release];
//此时因为str1
是一个常量,默认的引用计数是一个比较大的整数
NSLog(@"str1 addr = %p,str1.rc = %lu",str1,str1.retainCount);
//小
NSLog(@"str2 addr = %p,str2.rc = %lu",str2,str2.retainCount);
//小
NSLog(@"str3 addr = %p,str3.rc = %lu",str3,str3.retainCount);
//小
NSLog(@"str4 addr = %p,str4.rc = %lu",str4,str4.retainCount);
//小
NSLog(@"str5 addr = %p,str5.rc = %lu",str5,str5.retainCount);
//小
NSLog(@"str6 addr = %p,str6.rc = %lu",str6,str6.retainCount);
//小
NSLog(@"str7 addr = %p,str7.rc = %lu",str7,str7.retainCount);
//小
}
return 0;
/*
自动释放池的作用:
自动释放池结束的时候,会向自动释放池中所有的对象,发送一条 release
自动释放池的使用步骤:
1) 创建自动释放池
2) 把对象加入到自动释放中
怎么加入呢?
对象调用 autorelease
方法,就把该对象加入到栈顶的自动释放中了
*/
#import <Foundation/Foundation.h>
#import "Car.h"
int main(int argc,
const char *argv[]) {
@autoreleasepool {
Car *bigBen = [Car
new];
[bigBen
run];
[bigBen autorelease];
//把对象 bigBen
加入到自动释放池中
// [bigBen release];
}
// [bigBen release];
return 0;
NSString *homePath =
NSHomeDirectory();
//NSHomeDirectory 沙盒的根目录
NSLog(@"homePath = %@",homePath);
// "/"
NSString *tempPath =
NSTemporaryDirectory();
NSLog(@"tempPath = %@",tempPath);
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask, YES);
NSString *path = [paths
lastObject];
///Users/apple/Library/Developer/CoreSimulator/Devices/0B364173-7C28-4376-84F4-671126E16FAD/data/Containers/Data/Application/41568158-8808-49C5-A41D-6432A1F74D3B/Library/aaa/1.txt
//stringByAppendingPathComponent
给我们增加子路径
path = [path stringByAppendingPathComponent:@"aaa/1.txt"];
//Library
下创建一个文件夹 ,文件夹名是aaa/1.txt
NSLog(@"path = %@",path);
// NSFileManager *fm = [NSFileManager defaultManager];
// //在沙盒下Library中先创建目录
// [fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
NSString *str = @"abc";
BOOL isYes = [str
writeToFile:path atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
NSLog(@"%d",isYes);
——————————————————————————————
——————————————————————————————
1-对象所有权:
某个变量对指定的对象有使用权
2-引用计数
用来标识一个对象有几个使用者
3-引用计数器
记录使用者的个数的变量
变量类型 unsigned long
方法 retainCount
打印引用计数器的值 %lu
4-引用计数器的作用
作为对象是否要回收的依据
如果为0
要回收
如果>0
不要回收
5-对引用计数器的操作
向对象
发送 retain 消息 [obj retain];
使得对象的引用计数器+1
向对象
发送 release 消息
使得对象的引用计数器-1
6-对象回收注意:
一个对象如果回收的时候,系统自动的调用这个对象的 dealloc
方法
MRC - 手动内存管理
ARC - 自动引用计数管理 (默认的)
——————————————————————————————
//创建一个实例对象
Person *p = [Person
new];
//Person *p = [[Person alloc]init];
//对象引用计数器的值?
//[p retainCount];
可以获得对象的引用计数器的值
//对象创建完成后,默认的有一个所有者,就是他自己
NSUInteger n = [p
retainCount];
[p
retain]; //
让引用计数期的值+1
NSLog(@"n = %lu",n);
// 1
//release
可以让对象的引用计数器的值 -1
//如果对象的引用计数器的值
为 0
//那么此时这个对象会被立即回收
//会调用对象的 dealloc
方法(系统自动调用)
[p
release];
//0
//
//NSLog(@"p.retainCount = %lu",[p retainCount]); //
[p
release];
———————————内存管理的原则———————————————————
只要对象的引用计数不为0 ,这个对象就不能释放
使用某个对象之前,先retain
使用之后
然后 relase
口诀:
1)谁创建,谁释放
Person *p = [Person new];
Person *p1 = p;
[p release]; //谁创建谁release
2)谁retain
谁 release
Person *p = [Person new];
Person *p1 = p;
[p1 retain]; //谁retain
谁release
[p1 release];
[p release]; //谁创建谁release
野指针: 1)指针变量没有赋值 2)指向的空间已经不可用了
空指针:
谁都不指向
内存泄露:
申请的空间,没有及时的释放
——————————————————————————————
内存泄露: 申请了空间,到程序结束,你都没有任何释放空间的操作
单个对象的内存泄露问题
1) 创建了对象以后,没有释放
2) retain和release的个数不匹配问题
3) 对象使用的过程中赋值了nil
4) 在对象方法中不当的使用 retain
——————————————————————————————
set方法的内存管理问题:
1)对于基本数据类型的实例变量
int _age,float _height;
-(void)setAge:(int)age{
_age = age;
}
2) 对于对象类型的set方法,应该按照如下去写
Car *_car;
-(void)setCar:(Car *)car{
if(_car!=car){
[_car release];
_car = [car retain];
}
}
-(void)dealloc{
[_car release];
[super dealloc];
}
*/
——————————————————————————@perperty 参数————
1) 什么时候使用 assign?
基本数据类型的时候 int float double char
BOOL struct enum
2) 什么时候使用retain
如果实例变量是 OC对象类型的时候,要使用 retain
如果使用了retain
注意:
在 dealloc 方法,中要 release一次
——————————————————————————————
/*
assign 直接赋值
set方法没有使用retain
-(void)setDog:(Dog *)dog{
_dog = dog;
}
retain release旧的值,retain新的值
-(void)setDog:(Dog *)dog{
if(_dog != dog){
[ _dog release];
_dog = [dog retain];
}
}
——————————————————————————————
@property 参数分为三组
1) 原子性
atomic(默认) -
线程安全
nonatomic - 线程不安全(如果程序中没有使用多线程,建议使用这个)
2) 读写控制
readwrite(默认) -
生成get和set方法
readonly - 生成get方法
3) set内存管理
assign(默认) retain copy
——————————————————————————————
typedef struct T{
int hour;
int min;
int sec;
}Time;
//定义日期的结构体
typedef struct D{
//定义年月日
int year;
int month;
int day;
//定义时间
Time t;
}MyDate;
——————————————————————————————
@class 使用注意:
@class 用在.h文件中
用来告诉编译器这是一个类,这个类有哪些属性和行为,不会去立即检查
.m中如果使用 @class引入的这个类的属性和方法,都需要重新导入一次
这个类的头文件
——————————————————————————————
循环引用 一弱一强 assign retain
——————————————————————————————高
栈:
局部变量
堆:
动态申请的空间 对象
BSS: 没有初始化的全局变量和静态变量
数据区:已经初始化的全局变量和静态变量,字符串常量
代码区:程序编译后的代码的数据
低
//0x7fff5fbff7fc
int a = 10;
// 局部变量
//0x100000f82
char *s = "abc";
//字符串,数据区
NSLog(@"a addr = %p",&a);
//高地址
NSLog(@"s addr = %p",s);
//低地址
//0x100001070
NSString *str1 = @"abc";
//@"abc" 字符串常量 ,在常量区
NSString *str2 = [NSString
stringWithString:@"def"];
NSString *str3 = [[NSString
alloc] initWithString:@"abc"];
//0x100602420
//堆区
NSString *str4 = [NSString
stringWithFormat:@"aaa"];
NSString *str5 = [NSString
stringWithFormat:@"aaa"];
NSString *str6 = [[NSString
alloc] initWithFormat:@"bbbb"];
NSString *str7 = [[NSString
alloc] init];
[str7
release];
//此时因为str1
是一个常量,默认的引用计数是一个比较大的整数
NSLog(@"str1 addr = %p,str1.rc = %lu",str1,str1.retainCount);
//小
NSLog(@"str2 addr = %p,str2.rc = %lu",str2,str2.retainCount);
//小
NSLog(@"str3 addr = %p,str3.rc = %lu",str3,str3.retainCount);
//小
NSLog(@"str4 addr = %p,str4.rc = %lu",str4,str4.retainCount);
//小
NSLog(@"str5 addr = %p,str5.rc = %lu",str5,str5.retainCount);
//小
NSLog(@"str6 addr = %p,str6.rc = %lu",str6,str6.retainCount);
//小
NSLog(@"str7 addr = %p,str7.rc = %lu",str7,str7.retainCount);
//小
}
return 0;
自动释放池
——————————————————————————————/*
自动释放池的作用:
自动释放池结束的时候,会向自动释放池中所有的对象,发送一条 release
自动释放池的使用步骤:
1) 创建自动释放池
2) 把对象加入到自动释放中
怎么加入呢?
对象调用 autorelease
方法,就把该对象加入到栈顶的自动释放中了
*/
#import <Foundation/Foundation.h>
#import "Car.h"
int main(int argc,
const char *argv[]) {
@autoreleasepool {
Car *bigBen = [Car
new];
[bigBen
run];
[bigBen autorelease];
//把对象 bigBen
加入到自动释放池中
// [bigBen release];
}
// [bigBen release];
return 0;
———————————沙盒———————————————————
NSString *homePath =
NSHomeDirectory();
//NSHomeDirectory 沙盒的根目录
NSLog(@"homePath = %@",homePath);
// "/"
NSString *tempPath =
NSTemporaryDirectory();
NSLog(@"tempPath = %@",tempPath);
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask, YES);
NSString *path = [paths
lastObject];
///Users/apple/Library/Developer/CoreSimulator/Devices/0B364173-7C28-4376-84F4-671126E16FAD/data/Containers/Data/Application/41568158-8808-49C5-A41D-6432A1F74D3B/Library/aaa/1.txt
//stringByAppendingPathComponent
给我们增加子路径
path = [path stringByAppendingPathComponent:@"aaa/1.txt"];
//Library
下创建一个文件夹 ,文件夹名是aaa/1.txt
NSLog(@"path = %@",path);
// NSFileManager *fm = [NSFileManager defaultManager];
// //在沙盒下Library中先创建目录
// [fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
NSString *str = @"abc";
BOOL isYes = [str
writeToFile:path atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
NSLog(@"%d",isYes);
——————————————————————————————
——————————————————————————————
相关文章推荐
- HDU 1241 Oil Deposits
- 程序日志--ios“分歧解决器”程序
- Fine-Grained Histopathological Image Analysis via Robust Segmentation and Large-Scale Retrieval文章总结
- leetcode-20-Valid Parentheses
- 形形色色的下拉菜单 (菜单中文变英文+多级菜单)
- Android 四大组件学习之BroadcastReceiver四
- Mahout学习四--贝叶斯分类
- hdu 1533 Going Home (最小费用最大流)
- VC++中如何将字符串转换成整型数字
- DP SRM 661 Div2 Hard: ColorfulLineGraphsDiv2
- mac上安装mysql
- Android清除本地数据缓存代码
- BZOJ3456 : 城市规划
- 黑马程序员----基础题----我的基础题
- 动态类型检查
- 我不是蛤蟆!
- Android ViewPager多页面滑动切换以及动画效果
- 代码检查、走查和评审
- A New Tetris Game - HDU 1760 博弈
- C# 抽象类和接口的区别