iOS面试必看!谈谈NSString和NSMutableString的浅拷贝和深拷贝

本文探讨了NSString和NSMutableString在浅拷贝和深拷贝中的行为。浅拷贝对于NSString意味着引用计数增加,而深拷贝对于NSMutableString则会创建新的对象。在Objective-C中,使用copy关键字修饰属性可以防止可变对象意外修改。文章通过示例代码展示了copy和mutableCopy方法的使用及其效果,并解释了为何在特定情况下使用copy修饰符是必要的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字符串的浅拷贝和深拷贝

我们都知道@property修饰字符串时采用关键字copy,那是什么原因的,面试时常问的浅拷贝和深拷贝是什么呢?

  1. 我们先看一段代码,NSString对象调用copy方法控制台输出的name和str1地址是一样的,说明NSString没有创建新的对象,这种叫做浅拷贝,str2的地址和name的地址不同,通过断点我们知道str2指针其实是NSMutableString类型,调用mutableCopy方法创建了新的对象,返回NSMutableString类型的对象,叫做深拷贝。
    NSString *name = @"Billy";
    //copy方法浅拷贝
    NSString *str1 = [name copy];
    //mutableCopy方法深拷贝
    NSMutableString *str2 = [name mutableCopy];
       
    NSLog(@"###%p###%p###%p",name,str1,str2);
  1. 我们在来看NSMutableString类型字符串,NSMutableString对象调用copy方法,是深拷贝,创建一个新的对象,返回的是NSString类型,调用mutableCopy,是深拷贝,创建新的对象,返回NSMutableString类型。
    NSMutableString *name = [NSMutableString stringWithString:@"Billy"];
    //深拷贝
    NSString *str1 = [name copy];
    //深拷贝
    NSMutableString *str2 = [name mutableCopy];
    
    NSLog(@"###%p###%p###%p",name,str1,str2);
  1. @property修饰字符串时采用关键字copy,我们定义一个类People,有一个属性name,系统帮我们生成的setter方法其实如下代码
@interface People : NSObject

@property (nonatomic,copy) NSString *name;

@end

@implementation People

-(void)setName:(NSString *)name {
    
    _name = [name copy];
}

@end
  1. 为什么要使用copy修饰呢,看代码,我们采用NSString给对象的属性赋值时并没有影响
    People *p = [[People alloc]init];
    NSString *str = @"Billy";
    p.name = str;

    //修改str不会影响p.name的值,因为修改NSString会创建新的对象
    str = @"Jondan";

内存表示

  1. 我们采用NSMutableString给对象的属性赋值时,如果不调用copy,修改NSMutableString对象就会修改了属性的值,所以我们要使用copy
    People *p = [[People alloc]init];
    NSMutableString *str = [NSMutableString stringWithString:@"Billy"];
    p.name = str;
    
    //修改str不会影响p.name的值,因为setter里面调用了copy方法实现了深拷贝
    //p.name指向的对象和str指向的对象不是同一个对象
    [str appendString:@"Jondan"];

内存表示
6.重新给大家进行补充,People类有个属性brief

//用可变字符串赋值给不可变字符串
   People *p = [[People alloc] init];
    NSMutableString *str = [NSMutableString stringWithString:@"Hello!"];
    p.brief = str;
    [str appendString:@"ee"];
    NSLog(@"%p\n%p\n%@\n%@\n",str,p.brief,str,p.brief);
    //打印结果0x10076d3c0,0x10076d3c0,Hello!ee,Hello!ee

这种情况就一定要用copy来修饰,因为是用可变字符串给不可变字符串赋值,如果使用了strong来修饰,setter方法里不会调用copy方法,就不会创建新的对象,修改str就会修改了brief的值。

7.NSString用copy和strong的区别呢,如果给属性赋值时用不可变字符串给不可变字符串赋值,这种情况的话copy和strong都是一样的,OC中 NSString 为不可变字符串的时候,用 copy 和 strong 都是只分配一次内存,但是如果用 copy 的时候,需要先判断字符串是否是不可变字符串,如果是不可变字符串,就配空间,如果是可变字符串才分配空间。如果程序中用到 NSstring 的地方特别多,每都要先进行判断就会耗耗费性能,影响用户体验,用 strong 就不会再进行判断,所以,不可变字符串可以直接用 strong修饰。

    People *p = [[People alloc] init];
    NSString *string = @"Hello!";
    p.brief = str;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值