设为首页 加入收藏

TOP

Objective-C基础笔记(3)OC的内存管理(一)
2014-11-23 19:15:02 来源: 作者: 【 】 浏览:15
Tags:Objective-C 基础 笔记 内存 管理

Objective-C的内存基本管理

在OC中每个变量都保存着引用计数器,当这个对象的引用计数器为0的时候该对象会被回收。当使用alloc、new或者copy创建一个对象的时候,对象的引用计数器被置为1.

给对象发送一条retain消息,可以使引用计数器+1.

给对象发送一条release消息,可以使引用计数器-1.

当OC被销毁的时候会发送一条dealloc消息(不要直接调用,由系统调用),可以重写dealloc方法,在该方法中释放相关资源。

可以给对象发送retainCount消息获取对象的当前引用计数器。

首先我们新建一个工程

\

接下来将工程的设置里面将ARC禁掉

\

Book.h文件

#import 
  
   

@interface Book : NSObject

@property float price;

- (id)initBook:(float)price;

@end
  
Book.m文件

#import "Book.h"

@implementation Book

@synthesize price = _price;

//构造函数
- (id)initBook:(float)price {
    if(self = [super init]){
        _price = price;
    }
    NSLog(@"价格是%f的书购买了", _price);
    return self;
}

//析构函数
- (void)dealloc {
    NSLog(@"价格为%f的书被释放了", _price);
    [super dealloc];
}

@end
Student.h文件

#import 
  
   
#import "Book.h"

@interface Student : NSObject

@property int age;
@property Book *book;

- (void)setBook:(Book *)book;

- (id)initStudent:(int)age;

@end
  
Student.m文件

#import "Student.h"
#import "Book.h"

@implementation Student

@synthesize age = _age;
@synthesize book = _book;

- (void)setBook:(Book *)book {
    if(_book != book){
        //先对原来的书计数器减一
        //如果之前为nil不会出错(和java中的空指针不同)
        [_book release];
        [book retain];
        _book = book;
    }
}

//构造函数
- (id)initStudent:(int)age {
    if(self = [super init]) {
        _age = age;
    }
    NSLog(@"年龄为%d的学生被创建了", _age);
    return self;
}

//析构函数
- (void)dealloc{
    [_book release];
    NSLog(@"年龄为%d的学生被释放了", _age);
    [super dealloc];
}

@end
main.m文件

#import 
  
   
#import "Student.h"
#import "Book.h"

void buyBook(Student *stu) {
    Book *book1 = [[Book alloc] initBook:101.5]; //谁创建谁释放
    stu.book = book1;
    [book1 release];
    Book *book2 = [[Book alloc] initBook:98.5];
    stu.book = book2;
    [book2 release];
}

void readBook(Student *stu) {
    NSLog(@"年龄是%i的学生在读价格为%f的书", stu.age, stu.book.price);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //计数器为1
        Student *stu = [[Student alloc] initStudent:21];
        //买书
        buyBook(stu);
        //
   看书
        readBook(stu);
        //计数器清0,释放内存
        [stu release];
    }
    return 0;
}

  
输出结果:

2014-11-13 23:11:19.510 内存管理[698:46519] 年龄为21的学生被创建了

2014-11-13 23:11:19.512 内存管理[698:46519] 价格是101.500000的书购买了

2014-11-13 23:11:19.512 内存管理[698:46519] 价格是98.500000的书购买了

2014-11-13 23:11:19.512 内存管理[698:46519] 价格为101.500000的书被释放了

2014-11-13 23:11:19.512 内存管理[698:46519] 年龄是21的学生在读价格为98.500000的书

2014-11-13 23:11:19.512 内存管理[698:46519] 价格为98.500000的书被释放了

2014-11-13 23:11:19.512 内存管理[698:46519] 年龄为21的学生被释放了

@class关键字

通常引用一个类有两种方法,一种是通过#import,另一种是通过@class.

#import 的方式会将头文件中的所有信息引入。

@class 的方式只是说明它是一个类(假如只是声明一个类就不用使用#import).

#import 
  
   

@class Book; //声明Book是一个类

@interface Student : NSObject {
    Book *_book;
}

@property int age;
@property Book *book;

- (void)setBook:(Book *)book;

- (id)initStudent:(int)age;

@end
  
另外,Student.m中的析构函数我们可以做如下修改

//析构函数
- (void)dealloc{
    self.book = nil; //调用setter方法
    [_book release];
    NSLog(@"年龄为%d的学生被释放了", _age);
    [super dealloc];
}
self.book = nil; 会调用setter方法,释放对象并将当前类Student的属性_book设为nil.

@property的参数

@property的参数格式: @property (参数1, 参数2,...) 类型 名字;

参数主要分为3类:

读写属性:readwrite / readonly

setter处理: assign / retain / copy

原子性:atomic / nonatomic

说明:

readonly代表只生成getter方法,默认是readwrite

assing默认(直接赋值),copy是setter方法release旧值,再copy新值

atomic(默认),保证getter和setter的原子性,提供多线程安全访问,nonatomic性能高,所以一般是选择nonatomic.

#import 
  
   

@class Bo
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C指针解析 ------ 指针的算术运算 下一篇C学习笔记――malloc内存分配

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: