对于深拷贝以及浅拷贝的理解 为什么String用copy修饰

一,两种拷贝的意思

浅拷贝:也叫指针拷贝,拷贝后不会产生一个新的对象,指向原有对象同一内存地址,原有对象引用计时器加一,该对象会因原对象的改变而改变,实际内存并没有发生拷贝.

深拷贝:拷贝后会产生一个新的对象,指向不同的内存地址,拷贝后对象不会受到原有对象的影响,实际内存发生了拷贝

二,ios三种深浅拷贝:strong,copy和mutable copy 

创建一个Person的类

1,第一种情况 Person 里面name属性为strong的情况 

@interface Person : NSObject
@property(nonatomic,strong)NSString * name;
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person * people=[[Person alloc] init];
        NSString *name=[NSString stringWithFormat:@"名字"];

//等于号这里进行的复制
        people.name=name;
        NSLog(@"name的地址是%p",name);
        NSLog(@"people.name的地址是%p",people.name);
    }
    return 0;
}

控制台输出

两个地址一样 进行了浅复制

将name 的NSString改成NSMutableString 

NSMutableString *name=[NSMutableString stringWithFormat:@"名字"];

同样是进行了浅复制 ,两个属性使用同一个内存空间

此时name是可变的,修改name的值会改变people属性name的值

  Person * people=[[Person alloc] init];
        NSMutableString *name=[NSMutableString stringWithFormat:@"名字"];
        people.name=name;
        NSLog(@"people.name=%@",people.name);
        [name appendFormat:@"变了"];
        NSLog(@"name改变后的people.name=%@",people.name);
        

people的name因为原有name的改变而改变了.

2,第二种情况 Person里面 name的属性为copy

@interface Person : NSObject
@property(nonatomic,copy)NSString * name;
@end

按照上面的步骤实现一遍

无论外界的值是NSMutableString还是String 都不会改变Person类对象里面的name值

说明使用copy来修饰属性的话,在进行等于号赋值的时候,当外界对象是一个可变对象时为了防止互相影响会进行深拷贝。当然如果对象是一个不可变的对象的话就会进行浅拷贝,对象本来就不可变了,不会互相影响,没必要开多一片空间。

这也就是为什么NSString属性一般用copy来修饰。

总结:
oc中copy:利用一个源对象产生一个副本对象
特点:修改源对象不影响副本对象
修改副本对象不影响源对象
一个对象(可变或不可变)可以调用copy或mutablecopy
一个是创建的是不可变副本(nsstring,nsarray)
一个创建的是可变副本(nsmutablestring)
不是所有的类都遵循nscopy和nsmutable协议系统自带的类才遵循
 自己创建的person类是不能使用的

一般情况下拷贝会生成一个新的对象
为什么会产生一个新的对象
1.因为拷贝要求修改原来的对象不能影响到拷贝出来的对象
2,由于以前的对象是一个不可变的对象,而通过mutablecopy拷贝出来的对象必须是一个可变的对象,所以必须生成一个新的对象(此时已经改变对象的结构了)


如果通过不可变对象调用copy方法,那么不会生成一个新的对象
原因:因为原来的对象是不能修改的,拷贝出来的对象也是不能修改的
既然两个都不能修改,所有永远不能影响到另一个对象,那么已经符合需求了,性能优化

:正是因为调用copy方法有时候会生成一个新的对象,有时候不会生成一个新的东西
所以:如果没有创建新的对象就是浅拷贝就是指针拷贝
深拷贝会产生新的对象

总之不可变对象调用copy都不会产生新的对象,因为原本对象是不会变的,而不可变对象调用mutablecopy会产生新的对象,因为结构变了(从不可变变成可变)

可变对象调用mutablecopy和copy都会产生新的对象,因为原者和副本都可以改变,为了不互相影响所以产生新的对象

写得有点乱 不好意思 有什么讲的不清楚可以留言一起探讨一下

猜你喜欢

转载自blog.csdn.net/MChuajian/article/details/84450664