iOS 集合的深复制与浅复制

浅复制

浅复制就是对内存地址的复制, 让目标对象指针和源对象指向同一片内存空间. 如:

1
2
char* str = (char*)malloc(100);
char* str2 = str;

浅复制只是对对象的简单复制, 让几个对象共用一片内存, 当内存销毁的时候, 指向这片内存的几个指针需要重新定义才可以使用, 要不然会成为野指针

iOS 里面的浅复制:

在 iOS 里面, 使用 retain 增加引用计数(iOS 5以后有了 ARC 机制, 在 ARC 模式下 retain 关键字不可再主动使用), 就是一种更加保险的浅拷贝. 它既让几个指针共用同一片内存空间, 又可以在 release 由于计数的存在, 不会轻易的销毁内存, 达到更加简单使用的目的

深复制:

深复制是指复制对象的具体内容, 而内存地址是自主分配的, 复制结束之后, 两个对象虽然存的值是相同的, 但是内存地址不一样, 两个对象也互不影响, 互不干涉

copy 与 retain 的区别:

copy 是创建一个新对象, retain 是创建一个指针, 引用对象计数加一. copy 属性标识两个对象内容相同, 新的对象 retainCount 为1, 与旧有对象引用计数无关, 旧有对象没有变化. copy 减少对象对上下文的依赖

iOS里的深复制:

iOS 提供了 copy 和 mutableCopy 方法, 顾名思义, copy 就是复制了一个 immutable 的对象, 而 mutableCopy 就是复制了一个 mutable 的对象. 以下将举几个例子来说明, 这里指的是 NSString, NSNumber 等等一类的对象:

1
2
3
4
NSString *string = @"dddd";
NSString *stringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];

查看内存可以发现, string 和 stringCopy 指向的是同一块内存区域(weak reference), 引用计数没有发生改变. 而MstringMCopy 则是我们所说的真正意义上的复制, 系统为其分配了新内存, 是两个独立的字符串内容是一样的

拷贝构造:

当然在 iOS 中并不是所有的对象都支持copy, mutableCopy, 遵守 NSCopying 协议的类可以发送 copy 消息, 遵守 NSMutableCopying 协议的类才可以发送 mutableCopy 消息

假如发送了一个没有遵守上诉两协议而发送 copy 或者 mutableCopy, 那么就会发生异常. 但是默认的 iOS 类并没有遵守这两个协议. 如果想自定义一下 copy 那么就必须遵守 NSCopying, 并且实现 copyWithZone: 方法, mutableCopy 同理

如果是我们定义的对象, 那么我们自己要实现NSCopying , NSMutableCopying 这样就能调用 copy 和 mutablecopy 了. 举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@interface MyObj : NSObject<NSCopying, NSMutableCopying>
{
NSMutableString *_name;
NSString *_immutableStr ;
int _age;
}
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *immutableStr;
@property (nonatomic) int age;

//copy拷贝构造:
- (id)copyWithZone:(NSZone *)zone
{
MyObj *copy = [[[self class] allocWithZone :zone] init];
copy->name = [_name copy];
copy->immutableStr = [_immutableStr copy];
copy->age = age;
return copy;
}

//mutableCopy拷贝构造:
- (id)mutableCopyWithZone:(NSZone *)zone
{
MyObj *copy = NSCopyObject(self, 0, zone);
copy->name = [_name mutableCopy];
copy->age = age;
return copy;
}

0%