自己的网站中商城怎么做,遥阳科技网站建设,网站模板怎么设计,网上营业执照申请对象复制与拷贝 文章目录 对象复制与拷贝copy与mutablecopycopy与mutablecopy的简介示例#xff1a;不可变对象的复制可变对象的复制 NSCopying和NSMutableCopying协议深复刻和浅复刻浅拷贝#xff08;Shallow Copy#xff09;#xff1a;深拷贝#xff08;Deep Copy…对象复制与拷贝 文章目录 对象复制与拷贝copy与mutablecopycopy与mutablecopy的简介示例不可变对象的复制可变对象的复制  NSCopying和NSMutableCopying协议深复刻和浅复刻浅拷贝Shallow Copy深拷贝Deep Copy setter方法的复制选项  copy与mutablecopy 
copy与mutablecopy的简介 
 copy和mutablecopy都是NSObeject所提供用来复制对象的方法但它们有着不同的行为主要区别如下 
copy 方法 
copy 方法用于创建一个不可变的副本无论原始对象是可变的还是不可变的。对于不可变对象copy 方法仅仅是增加了引用计数返回的仍然是原始对象本身。对于可变对象copy 方法会创建一个新的不可变对象内容与原始对象相同。 
mutableCopy 方法 
mutableCopy 方法用于创建一个可变的副本无论原始对象是可变的还是不可变的。对于不可变对象mutableCopy 方法会创建一个新的可变对象内容与原始对象相同。对于可变对象mutableCopy 方法会创建一个新的可变对象内容与原始对象相同。 
总结一下主要区别在于 
copy 返回的是不可变副本而 mutableCopy 返回的是可变副本。copy 对不可变对象和可变对象的行为不同而 mutableCopy 则对所有对象的行为都一致。 
示例 
不可变对象的复制 
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {NSString* str1  deer;NSString* str2  str1;NSString* strcopy  [str1 copy];NSString* strmutablecopy  [str1 mutableCopy];NSLog(%p,str1);NSLog(%p,str2);NSLog(%p,strcopy);NSLog(%p,strmutablecopy);}return 0;
}不难看出来str1,str2, strcopy ,指向的都为同一内存区域为浅拷贝由于mutablecopy生成了新的NSMutableString所以系统为其重新开辟一块空间进行了深拷贝。 
可变对象的复制 
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {NSMutableString *mstr  [NSMutableString stringWithString:hello];NSString *mstrcopy1  [mstr copy];NSMutableString *mstrcopy2  [mstr copy];NSMutableString *mstrmutablecopy  [mstr mutableCopy];[mstr appendString:,aa];//[mstrcopy2 appendString:,bb];[mstrmutablecopy appendString:,cc];NSLog(%p,mstr);NSLog(%p,mstrcopy1);NSLog(%p,mstrcopy2);NSLog(%p,mstrmutablecopy);}return 0;
}对于注释的那一句代码由于mstrcopy是通过copy方法得来类型为NSString是不可变的所以后面无法进行追加。可以发现通过copy得到的字符串指向的是同一片地址但是复制得到的地址相对于原来的mstr都是不同的所以我们可以知道对于可变对象进行copy和mutablecopy都是进行深拷贝。 
NSCopying和NSMutableCopying协议 
虽然NSObject虽然都给出了copy和mutablecopy的方法但是不一定在任何时候都能够使用为了确保一个对象可以调用copy方法复制得到自身的不可变副本我们需要做如下事情 
让该类实现NSCopying协议让该类实现copyWithZone方法 
对于mutablecopy也是同理 
实现NSMutableCopying协议让该类实现mutableCopyWithZone方法 
#import Foundation/Foundation.hinterface MyObject : NSObject NSCopyingproperty (nonatomic, strong) NSMutableString *name;
property (nonatomic, assign) int age;endimplementation MyObject- (id)copyWithZone:(NSZone *)zone {MyObject *copy  [[[self class] allocWithZone:zone] init];// 递归复制子对象copy.name  self.name;copy.age  self.age;return copy;
}-(NSString*)description {return [NSString stringWithFormat:name  %, age  %d, self.name, self.age];
}
endint main(int argc, const char * argv[]) {autoreleasepool {// 创建原始对象MyObject *org  [MyObject new];org.name  [NSMutableString stringWithString:aa];org.age  10;NSLog(%,org);MyObject *copy1  [org copy];NSLog(%,copy1);copy1.name  [NSMutableString stringWithString:bb];copy1.age  20;NSLog(%,org);NSLog(%,copy1);}return 0;
}从以上程序我们看出来我们对org进行一次副本复制对得到的copy的成员变量进行赋值对org不会产生影响。 #import Foundation/Foundation.hinterface MyObject : NSObject NSCopyingproperty (nonatomic, strong) NSMutableString *name;
property (nonatomic, assign) int age;endimplementation MyObject- (id)copyWithZone:(NSZone *)zone {MyObject *copy  [[[self class] allocWithZone:zone] init];// 递归复制子对象copy.name  self.name;copy.age  self.age;return copy;
}-(NSString*)description {return [NSString stringWithFormat:name  %, age  %d, self.name, self.age];
}
endint main(int argc, const char * argv[]) {autoreleasepool {// 创建原始对象MyObject *org  [MyObject new];org.name  [NSMutableString stringWithString:aa];org.age  10;NSLog(%,org);MyObject *copy1  [org copy];NSLog(%,copy1);}return 0;
}深复刻和浅复刻 
深拷贝Deep Copy和浅拷贝Shallow Copy是在编程中经常遇到的两个概念它们描述了在复制对象时复制的内容的不同程度。 
浅拷贝Shallow Copy 
浅拷贝是指将一个对象复制到一个新的对象中即将对内存指针的复制并增加其引用计数。如果对象包含其他对象的引用浅拷贝将不会复制这些引用的对象而是将其引用复制到新对象中。因此新对象和原对象中的引用指向相同的对象。如果其中一个对象修改了共享对象另一个对象也会受到影响。当使用A指针改变内容时B指针指向的内容也会跟着改变 深拷贝Deep Copy 
深拷贝是指将一个对象递归复制到一个新的对象中开辟一片新的空间并且复制所有引用的对象直至没有任何共用的部分。这意味着新对象中的每个对象都是原始对象的副本而不是共享的。因此如果其中一个对象修改了它指针所指向的对象另一个对象不会受到影响。 对于上图来说分配了新的内存改变A指针指向的值不会影响到指针B指向值的内容。 通常情况下浅拷贝的效率比深拷贝高因为它不需要递归地复制所有引用的对象。但是在需要保持对象之间的独立性时深拷贝是必需的。 
我们再来探究一下我们刚刚看到的例子 
#import Foundation/Foundation.hinterface MyObject : NSObject NSCopyingproperty (nonatomic, strong) NSMutableString *name;
property (nonatomic, assign) int age;endimplementation MyObject- (id)copyWithZone:(NSZone *)zone {MyObject *copy  [[[self class] allocWithZone:zone] init];// 递归复制子对象copy.name  self.name;copy.age  self.age;return copy;
}-(NSString*)description {return [NSString stringWithFormat:name  %, age  %d, self.name, self.age];
}
endint main(int argc, const char * argv[]) {autoreleasepool {// 创建原始对象MyObject *org  [MyObject new];org.name  [NSMutableString stringWithString:aa];org.age  10;NSLog(%,org);MyObject *copy1  [org copy];NSLog(%,copy1);[copy1.name replaceCharactersInRange:NSMakeRange(0,2) withString:bb];copy1.age  20;NSLog(%,copy1);NSLog(%,org);}return 0;
} 
我们的程序输出以下结果。 似乎很奇怪我们通过repalce的函数去修改字符串使得org和copy的字符串内容都发生了改变想要解决这个问题我们可以画一个图来辅助我们进行理解。 对于即将被复制的org来说变量name之中存储的是字符串的地址指针而不是字符串本身如果进行copy.name  self.name; copy.age  self.age;那么只是将字符串的地址赋给copy之中的name属性实际上两者指针都指向一个相同的NSMutableString类型字符串。 对于这种复制模式我们就称之为浅复制在内存中复制一个对象但是原来的和复制得到的内容指向一个相同的对象也就是说两个对象都存在依然存在的部分 
那如果要实现深复制呢前面说过深复制不仅会对对象本身进行复制而且还会递归复制每一个指针的属性直到两者没有共同的部分。我们将copyWithZone的代码进行一些修改就能实现深复制的原理。 
- (id)copyWithZone:(NSZone *)zone {MyObject *copy  [[[self class] allocWithZone:zone] init];// 递归复制子对象copy.name  [self.name mutableCopy];copy.age  self.age;return copy;
}我们将原对象的属性值复制了一份可变的副本再将新的可变副本的内容赋值给新对象的name属性与原先的对象再无共用的部分实现了深复制 
一般来说实现深复制的难度很大对于包含大量指针属性的对象来说更或者对象中的变量中又嵌套了一层指针的话那会更加复杂 
setter方法的复制选项 
当属性声明为 copy 时在 setter 方法中会执行深复制操作。这意味着在设置属性值时会创建一个属性值的副本而不是直接引用传入的对象。 
考虑以下代码 
property (nonatomic, copy) NSString *name;对应的 setter 方法会类似于这样 
- (void)setName:(NSString *)name {if (_name ! name) {_name  [name copy];}
}在这个 setter 方法中首先进行了对象的比较确保新值和旧值不是同一个对象。然后使用 copy 方法来创建新值的副本并将副本赋值给属性 _name。这样做可以确保属性值的安全性防止外部对象对属性值的意外修改。 
copy 操作实际上是执行了浅复制它只会复制对象的指针而不会复制对象本身。这意味着它会创建一个新的指针指向相同的内存地址而不是创建一个完全独立的副本。 
对于不可变对象由于其内容是不可变的因此可以安全地使用 copy 属性。对于可变对象而言使用copy可能会导致意外的行为。因为修改一个对象会影响到所有指向该对象的指针。这就是为什么使用 copy 属性时需要小心特别是。另外如果属性值是可变对象那么每次设置属性值时都会创建一个新的不可变副本这样会导致性能开销增加。 
需要注意的是copy 属性通常适用于容器类对象和其他可复制的对象但对于自定义类对象需要确保其实现了 NSCopying 协议。否则编译器会报错。