手动管理内存整理

 //强调:面试 99%会问到

 

 创建对象

 1.分配内存空间,存储对象

 2.初始化成员变量

 3.反回对象的指针地址

 

 //1.对象在完成创建的同时,内部会自动创建一个引用计数器,这个计数器,是系统用来判断是否回收对象的唯一依据,当我们的引用计数retainCount = 0的时候,系统会毫不犹豫回收当前对象

 //2.[对象 release]  reatinCount - 1

 //3.[对象 retain]   reatinCount + 1 ,返回self

 //4.我们的引用计数retainCount = 0的 对象就被销毁了

 

 //5.dealloc函数,当一个对象要被销毁的时候,系统会自动调用dealloc函数,通知对象你将要被销毁

 

 //内存管理原则(配对原则):只要出现了 new,alloc,retain,就一定配对出现一个release,autorelease

 

//内存管理原则(配对原则):只要出现了 new,alloc,retain,就一定配对出现一个release,autorelease

//手动内存管理研究问题方法

//1.野指针操作

//2.内存泄漏

 

#import <Foundation/Foundation.h>

#import "Person.h"

 

void test()

{

    //retainCount = 1

    Person * p = [[Person alloc] init];

    

    p.age = 10;

    NSLog(@"%@",p);

    

    //retainCount = 0

    //系统已经将p所指向的对象回收了

    //EXC_BAD_ACCESS 访问了不可访问的内存空间

    //被系统回收的对象我们称之为僵尸对象

    //默认情况下xcode为了提高编码效率,不会时时检查僵尸对象

    

    [p release];

    

    //        NSLog(@"p所指向的对象回收了 %@",p);

    //        p.age = 20;//[p setAge:20];

    [p run];

 

}

 

void test2()

{

    Person * p = [[Person alloc] init];

    p.age = 20;

    

    NSLog(@"%@",p);

    

    [p release];

    //如果你确定当前作用于中的对象已经不会再被使用了,为了防止野指针操作,通常我们会把不在使用的指针变量赋值为nil

    p = nil;

    

    p.age = 30;//[nil setAge:30];

    [p run]; //[nil run];

    //避免野指针操作的方法 [nil resele]

 

}

void test3()

{

    /*

     //内存泄漏第一种情况

     //1

     Person * p = [[Person alloc] init];

     

     p.age = 20;

     NSLog(@"%@",p);

     //2

     [p retain];

     

     //3

     [p retain];

     

     //2

     [p release];

     

     //只要对象的retainCount != 0 就会一直存在在内存中

     //内存泄漏指的就是,不再被使用的对象,一直在内存中没有被销毁

     */

    

    /*

     //内存泄漏第二种情况

     //retainCount = 1

     Person * p = [[Person alloc] init];

     p.age = 20;

     [p run];

     

     

     p = nil;

     

     

     [p release];//[nil release];

     */

    

    //1

    Person * p = [[Person alloc] init];

    

    p.age = 20;

    [p run];

    

    Person * p1 = p;

    

    //0

    //        [p release];

    [p1 release];

    

    //野指针操作

    p1.age = 20;

 

}

void test4()

{

    //1

    Person * p = [[Person alloc] init];

    

    p.age = 20;

    NSLog(@"%@",p);

    

    //0

    [p release];

    

    //野指针操作,当一个对象retainCount已经为0 时,调用retain方法,是不会使得对象起死回生的,同时还会发生野指针操作异常

    [p retain];

}

 

void test5(Person * p)

{

    p.age = 30;// release retain

    [p retain]; //2

//    [p release];

    NSLog(@"%@",p);

}

 

int main(int argc, const char * argv[])

{

 

    @autoreleasepool {

        

        //1

        Person * p = [[Person alloc] init];

        p.age = 20;

        

//        test5(p);

        //1

        [p release];

        //0

        [p release];

   

    }

    return 0;

}

 

 

//1.生产get与set方法的声明

//2.生成get与set方法的简单实现

//3.若果你没有声成名相对象的成员变量,那么他会自动生成一个_开头的成员变量

 

//@property 参数分为4类

/*

1.与set方法内存管理相关参数

retain: 要生成符合内存管理原则的set方法(应用与对象类型)

assign: 直接赋值,(对象类型,基本数据类型)

copy :  (后面讲解)

*/

 

//2.多线程相关

//nonatomic: 不生成多线程线管代码,使用这个就可以了(效率高一点)

//atomic:生成多线程线管代码(不写默认是这种方式)

//实际开发中,只要是对象类型的@property都写成下面

 

//3.是否要生成set与get方法

//readwrite: 可读可写属性,同时生成set与get方法

//readonly : 只读属性,只生成get方法

 

//4.set与get方法名称相关的参数

//setter:设置生成的set方法名称

//getter:设置生成的get方法名称

 

//内存管理原则(配对原则):只要出现了new,alloc,retain方法,就要配对出现release,autorelease

//对象存入到自动释放池中,当这个池子被销毁的时候他会对池子中所有的对象进行一次release操作

//怎么把对象存到池子中

#import <Foundation/Foundation.h>

#import "Person.h"

 

int main(int argc, const char * argv[])

{

    /* 示例1

    //自动释放池

    //大括号代表池子的作用域

    @autoreleasepool

    {

        

     //release 功能 retaincount - 1

     //autorelease 好像功能也是 retaincount - 1 ?

        //1

        Person * p = [[Person alloc] init];

//        [p release];//retainCount立即 -1

        [p autorelease]; //autorelease方法的作用只是将对象放入到池子中,然后返回一个self

        

        NSLog(@"asdfasdf");

        

     }//代表,池子将要被销毁,对池子中所有的对象进行一次release操作,[p release] 0

     */

    

    /*

    //autoreleasepool我么可以自己随意的创建

    

    // 示例2

    //1//不管你这个对象时在@autoreleasepool 之内创建的还是在之外创建的,只要你在池子中调用了autorelease那么这个对象就会被放入到池子中

    Person * p = [[Person alloc ] init];

    

    @autoreleasepool {

        

        [p autorelease];

        

    }//p 0

    */

    // 示例3

    /*

    //1 只有在自动释放池的作用域中调用对象的autorelease方法才能够正确的讲对象放入到池子中

    Person * p = [[Person alloc] init];

    [p autorelease];

    

    NSLog(@"aaaa");

    @autoreleasepool {

        

    }

    NSLog(@"bbb");

     */

    //示例4

    /*

    // 1

    Person *  p = [[Person alloc] init];

    

    @autoreleasepool {

        

        [p autorelease];//加入第一次

        

        [p autorelease];//加入第二次

        

        NSLog(@"abc");

    }//[p release]0 [p release]

    

     NSLog(@"cbd");

    */

    

    //示例5

    /*

    //1

    Person * p = [[Person alloc] init];

    

    @autoreleasepool {

        

        @autoreleasepool {

            

            [p autorelease];

        }//?[p release] 0

        

    }

    */

    

    

    Person * p = [[Person alloc] init];

    

    @autoreleasepool {

        

        [p autorelease];

        

        @autoreleasepool {

            

         

            [p autorelease];

        }//[p release] 0

        

        

    }//[p release];

    

    

    return 0;

}

 

//ARC简单,不用程序员在去管理内存
//1.强指针 Strong
//2.弱指针 weak

//只要有强指针指向一个对象,那么系统就不会回收该对象
//只要没有强指针指向对象,系统立即回收该对象

//弱指针不影响,对象被回收

//默认情况下,所有的指针都是强指针类型

 

//创建出来就会立即被释放掉,应为没有强指针指向该对象
__weak Person * p = [[Person alloc] init];

- (void)dealloc
{
// [super dealloc];不能够在调用
// releae retain 在ARC机制中不能够在去手动调用
NSLog(@"Person 被释放了");
}

 

@interface Person : NSObject

 

//@property(nonatomic,retain)Car * car;

//ARC机制 strong 对象,手动内存管理的retain关键字,(一定能够都是应用在对象类型变量上)

//ARC机制中的 weak 对象手动内存管理的assign关键字,(一定能够都是应用在对象类型变量上)

@property (nonatomic,strong)Car * car;//强指针类型的对象,会影响对象回收

@property (nonatomic,weak)Car * car2;// 弱指针类型的对象,不会影响对象的回收

//@property (nonatomic,assign)Car * car3;//造成迷惑,会导致许多程序员搞不清这个变量到底是stong类型的还是weak类型

 

@property (nonatomic,strong)NSString * name;

@property (nonatomic,strong)NSString * idCard;

 

//ARC机制下 基本数据类型的@property参数使用,与手动内存管理完全一致

@property (nonatomic,assign)int age;

 

#import <Foundation/Foundation.h>
//#import "Person.h"
@class Person;

@interface Car : NSObject

//@property (nonatomic,strong)Person * p;

//当出现类循环应用的时候,只需要把一方面的Strong引用改为weak,并且在.h文件中使用@class 类名的方式,通知.h文件类的存在
@property (nonatomic,weak)Person * p;

 

你可能感兴趣的:(内存)