zoukankan      html  css  js  c++  java
  • iOS手动管理内存

        虽然iOS已经有了ARC帮你自动管理内存,但在有些项目中必须采用手动的方式,而且在懂得手动管理内存的情况下会是自己的代码更加完善

    众所周知,基于手动管理内存的情况下必然涉及到 relese  retain autorelese copy 等。

    其中 relese就是把对象的引用计数减一    retain表示把对象的引用计数加一   autorelese则是为一个叫做  内存池 的东西准备的  

     @autoreleasepool {

           

        }

    当你创建的对象加入到了内存池中,并且创建对象时用了  autorelese,则当内存池销毁时会自动帮对象调用autorelese 

    而copy则是拷贝一份 此时原有的对象其引用计数并不增加  ,当然涉及到拷贝的话又分为 浅拷贝 和 深拷贝, 不懂得可以上网查 很多的。

     上面这张图是官网上的。可以看看  描述的挺好的。下面通过一点小代码来说明下今天的主题:

    注意:relese autorelese  retain  他们操作的是对象的引用计数  而对于该变量本身是无影响的(除非所指的对象引用计数为零了),

    如:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        NSString *a = [[NSString alloc]initWithUTF8String:"women"];//a所指的对象引用计数为1
        
      
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"a = %@ ",a);
        NSString *b = a;//b 和 a 指向同一个对象
        [b retain];//b 把 应用计数加一了
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"b   reference is : %d",b.retainCount);
        NSLog(@"b = %@ ",b);
    
        [a release];
        
        NSLog(@"after a relese a  reference is : %d",a.retainCount);
        NSLog(@"agter a relese b   reference is : %d",b.retainCount);
        NSLog(@"a = %@ ",a);
        NSLog(@"b = %@ ",b);
    
    }
    View Code

    上面代码的输出:

    2013-07-30 18:53:02.679 MemoryDemo[4892:c07] a  reference is : 1

    2013-07-30 18:53:02.680 MemoryDemo[4892:c07] a = women 

    2013-07-30 18:53:02.681 MemoryDemo[4892:c07] a  reference is : 2

    2013-07-30 18:53:02.681 MemoryDemo[4892:c07] b   reference is : 2

    2013-07-30 18:53:02.682 MemoryDemo[4892:c07] b = women 

    2013-07-30 18:53:02.682 MemoryDemo[4892:c07] after a relese a  reference is : 1

    2013-07-30 18:53:02.683 MemoryDemo[4892:c07] agter a relese b   reference is : 1

    2013-07-30 18:53:02.684 MemoryDemo[4892:c07] a = women 

    2013-07-30 18:53:02.685 MemoryDemo[4892:c07] b = women 

     相信很容易懂吧。但如果此时我再调用下  [a relese];可以这样吗,a不是已经调用过了relese吗 ?还可以再调用一次 ,当然可以,因为relese操作的只是a 所指对象的引用计数,而不是 把 a 给消失掉了,好吧,我们把代码加上  ,再打印下(又陷阱的)。。。。

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        NSString *a = [[NSString alloc]initWithUTF8String:"women"];//a所指的对象引用计数为1
        
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"a = %@ ",a);
        NSString *b = a;//b 和 a 指向同一个对象
        [b retain];//b 把 应用计数加一了
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"b   reference is : %d",b.retainCount);
        NSLog(@"b = %@ ",b);
    
        [a release];
        
        NSLog(@"after a relese a  reference is : %d",a.retainCount);
        NSLog(@"agter a relese b   reference is : %d",b.retainCount);
        NSLog(@"a = %@ ",a);
        NSLog(@"b = %@ ",b);
    
        //新加上的
        [a release];
        NSLog(@"after a relese a  reference is : %d",a.retainCount);
       NSLog(@"agter a relese b   reference is : %d",b.retainCount);
    }
    View Code

     呵呵  ,崩掉了吧  ! 罪魁祸首就在最后的NSLog(),  a再次 relese时  他所指的对象的引用计数已经为零了 ,此时对象已经消失了 ,你再去给他发送消息  ,当然死掉咯

    接着看。。。。。

    你说一个对象的引用计数有可能为负数吗?? 上面的代码不是因为最后两行不能运行吗? 那你试着把第一行改为

    NSString *a = [[NSStringalloc]initWithString:@"women"];

    你会看到他正常运行  输出如:

    2013-07-30 19:19:19.522 MemoryDemo[5082:c07] a  reference is : -1

    2013-07-30 19:19:19.523 MemoryDemo[5082:c07] a = women 

    2013-07-30 19:19:19.524 MemoryDemo[5082:c07] a  reference is : -1

    2013-07-30 19:19:19.524 MemoryDemo[5082:c07] b   reference is : -1

    2013-07-30 19:19:19.525 MemoryDemo[5082:c07] b = women 

    2013-07-30 19:19:19.525 MemoryDemo[5082:c07] after a relese a  reference is : -1

    2013-07-30 19:19:19.526 MemoryDemo[5082:c07] agter a relese b   reference is : -1

    2013-07-30 19:19:19.526 MemoryDemo[5082:c07] a = women 

    2013-07-30 19:19:19.527 MemoryDemo[5082:c07] b = women 

    2013-07-30 19:19:19.527 MemoryDemo[5082:c07] after a relese a  reference is : -1

    2013-07-30 19:19:19.527 MemoryDemo[5082:c07] agter a relese b   reference is : -1

    怎么可能,而且全都是-1  ,这时因为这是一个NSString的常量 ,他一直处在 字符串常量池 中 ,生命周期为整个程序  ,所以你看到本来应该崩掉的代码正常运行,

    但此时对象的引用计数永远为-1  代表无穷大。。。

    最后再来看看,下面的例子: 

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        //NSString *a = [[NSString alloc]initWithString:@"women"];
        
        NSString *a = [NSString stringWithUTF8String:"women"];
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"a = %@ ",a);
        NSString *b = a;//b 和 a 指向同一个对象
        [b retain];//b 把 应用计数加一了
        NSLog(@"a  reference is : %d",a.retainCount);
        NSLog(@"b   reference is : %d",b.retainCount);
        NSLog(@"b = %@ ",b);
    
        [a release];
        
        NSLog(@"after a relese a  reference is : %d",a.retainCount);
        NSLog(@"agter a relese b   reference is : %d",b.retainCount);
        NSLog(@"a = %@ ",a);
        NSLog(@"b = %@ ",b);
    
    
        [a release];
        //NSLog(@"after a relese a  reference is : %d",a.retainCount);
      // NSLog(@"agter a relese b   reference is : %d",b.retainCount);
    }

    上面的代码主要是把第一句  初始化方法改为了  静态的类方法  非 alloc的 

    运行试试  崩掉了吧  。。。为什么这也会绷掉呢 ??

    这就是autorelese搞的鬼了 ,但好像没看到 autorelese啊  

    呵呵,这就要怪苹果公司了  他们写的这个方法

    NSString *a = [NSString stringWithUTF8String:"women"];
    是在后面加了 autorelese的,几乎我所知道的所有的类似这样的 [NSString stringWith...] [UIImage imageWith.....]

    [NSArray arrayWith....]等等 ,他们实现的时候都是加入了autorelese的  ,既然你加入了autorelese ,而程序的main.c函数中又有

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

    {

        @autoreleasepool {

            returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegateclass]));

        }

    }

     呵呵 ,这下知道了吧,,你的程序会自动给  在你加入了autorelese的对象  发送relese消息,但此时最后一句代码

    [a relese]已经把对象的引用计数变为零了。。。。人家当然不干了 ,所以在我们遇到这样的类似初始化方法时  ,千万要记住 autorelse这个东西。

    完结吧!

  • 相关阅读:
    析构函数可以内联吗(可以,但不建议)
    auto_ptr
    Oracle Enterprise Linux 6.0配置本地yum
    标准C++输入输出和字符串类学习小程序集锦
    [转载]解决mysql“Access denied for user 'root'@'localhost'”
    [Linux网络编程学习笔记]套接字地址结构
    javascript基础
    java学习笔记14动态代理
    2013面试总结_01
    jquery实现复选框checkbox全选(完善)
  • 原文地址:https://www.cnblogs.com/ctaodream/p/3225826.html
Copyright © 2011-2022 走看看