zoukankan      html  css  js  c++  java
  • 初学者关于内存的思考(不断加深不断更新中)

    1、

    从最简单的说起,先看例子,看注释:

    -(void)fun1
    {
    str1 = @"我是str1";
    NSLog(@"str1的conut: %d",[str1 retainCount]);//-1 之所以为-1,是因为直接赋值后,"我是str1"被放在常量区,没有所谓引用
    }

    -(void) fun2
    {
    str2 = [NSString stringWithFormat:@"我是str2"];
    NSLog(@"str2的count: %d",[str2 retainCount]);//1。注意:stringWithFormat里面已经包含alloc和autorelease了
      //[str2 release];如果加了这句,程序就崩溃。因为已经包含了autorelese,下面fun4的str2就是非法引用
    }

    -(void) fun3
    {
    str3 = [[NSString alloc]init];
    str3 = @"我是str3";
    NSLog(@"str3的count: %d",[str3 retainCount]);//-1 alloc跟init被忽略了,效果如fun1
    }

    -(void) fun4
    {
    NSLog(@"str2:%@",str2);
    NSLog(@"str1:%@",str1);
      NSLog(@"str3:%@",str3);
    }

    在外面:
        NSLog(@"str2 final count:%d",[str2 retainCount]);//1 仍旧是1,因为由编译器来负责管理(autorelease)
        NSLog(@"str3 final count:%d",[str3 retainCount]);//-1

    由上面的代码示例可以看出直接赋值跟用*with*方法赋值的区别。

    stringWithFormat里面已经包含alloc和autorelease。确切地说,*with*方法都包含了alloc以及autorelease

    2、
    在声明为@property (nonatomic, retain) UIAlertView *alert时,这里的retain不是摆设,而是retain了一次,这就刚好跟dealloc对应,在dealloc里面release
    计数器加1了。所以在还没alloc之前,retainCount为1。
    在.h中声明alert为成员变量,并设为property的retain属性   

    UIAlertView *tmpAlert = [[UIAlertView alloc]initWithTitle:tempStr
    message:nil
    delegate:self
    cancelButtonTitle:@"取消"
    otherButtonTitles:@"确定",nil];
    self.alert = tmpAlert;
    [tmpAlert release];
    [alert addSubview:view];
    [alert show];
    在上例子中,一般就这么用,不要直接轻易去对alert进行alloc,这样很容易出错。常见的做法如上,设一个临时变量tmpAlert,赋值给alert后就release掉。注意,是赋值
    给self.alert,而不是alert。别忘了,self.alert = tmpAlert 这句话等价于[alert release];alert = [tmpAlert retain];(为什么?)所以,为了避免额外的
    错误,尽量在.h中声明property/retain属性,要赋值的时候就用self.***。


    3、成员变量跟property不一定要对应存在,没有成员变量只有property也是合法的,self.***访问的就是property。

    4、对一个尚未分配内存的变量进行release是合法的。但是一旦你alloc+init了之后,就不能那么随便release。请看下面比较:
        UIAlertView *alert = nil;
        [alert release];//正确
        
        UIAlertView *alert2 = [[UIAlertView alloc] init];
        [alert release];
        [alert release];//报错
        
        NSString *str = nil;
        [str release];//正确
        
        NSString *str2 = [[NSString alloc] init];
        [str2 release];
        [str2 release];//正确!!!!!

    可以看出,NSString类型是个特列,不管你有没有alloc分配内存给他,都可以随时release。

    从这个例子我们也可以看出,对于工程里面的成员变量,不应该随意去设@property属性,因为这样会暴露给别的类。但是这时候会有这样的烦恼,没有了(retain),似乎后面的内存管理会变得麻烦些。所以产生了另外一种方式,在.m文件里面,凡是用该成员变量(假设为A)的地方,首先要在init里面把A置为nil,这是为了后面release的方便,不会出错(对nil对象release是不出错的)。然后凡是对该变量进行赋值的地方,都要先release,赋值完后再retain,养成习惯吧,兄弟。

    5、@property、@synthesize

    这两个关键字是让成员变量生成相应的setter、getter。setter里面已经包含了必要的retain、release。平时我们用self.****就是访问setter,而没加self的就是访问普通的成员变量。

    看个例子:

     @interface Photo : NSObject

    {

    NSString* caption;

    NSString* photographer;

    }

    - (NSString*) caption;//getter 

    - (NSString*) photographer;

    - (void) setCaption: (NSString*)input;//setter,注意其默认的名字set+***

    - (void) setPhotographer: (NSString*)input;

    @end

    用@property实现简化如下:

    @interface Photo : NSObject

    {

    NSString* caption;

    NSString* photographer;

    }

    @property (retain) NSString* caption;

    @property (retain) NSString* photographer;

    @end

    这里的retain意思是,setter应该对input进行retain。
    http://cocoadevcentral.com/d/learn_objectivec/                    原链接

    - (void) dealloc

    {

    self.caption = nil;

    self.photographer = nil;

    [super dealloc];

    }

    6.下面介绍几个个人比较容易混淆的东西,非常实用!先总说一下,原则是:

    原则1:往数组里填东西或者删除东西,数组本身的引用计数不改变!!!!,变的是被拿去添加的元素,引用计数相应增减

    原则2:往view添加subview或者removeview,superView本身引用计数都不改变!!!变的是被拿去添加的subview,引用计数相应增减

    原则3:subview可分为两种,一种是不需要控制的静态view,一种是被设为成员变量长期控制的动态view。 假设subview添加到superview中,并且以后不打算做改变,则应这么写:

    uiview *subview = new subview;//subview:1

    //若是动态view,则是_subView = new subview;//subview:1

    [superView addSubView:subview];//subview:2, superview:1

    [subview release];//subview:1

    静态view:在dealloc中就不用再释放了!因为大原则是“谁申请谁释放”,你只申请了一次,自然只需要释放一次。剩下的1个引用什么时候减掉呢?当superView释放的时候自己释放掉!

    动态view:若是动态view,则完全可以跟静态view一样,这样的话Dealloc里面就是空空的,这也是可以的;另一种是在上述步骤中不做release操作,统统保留到dealloc中做






  • 相关阅读:
    LeetCode 811. Subdomain Visit Count (子域名访问计数)
    LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)
    LeetCode 939. Minimum Area Rectangle (最小面积矩形)
    LeetCode 781. Rabbits in Forest (森林中的兔子)
    LeetCode 739. Daily Temperatures (每日温度)
    三种方式实现按钮的点击事件
    239. Sliding Window Maximum
    14.TCP的坚持定时器和保活定时器
    13.TCP的超时与重传
    12.TCP的成块数据流
  • 原文地址:https://www.cnblogs.com/wengzilin/p/2398083.html
Copyright © 2011-2022 走看看