对于深拷贝和浅拷贝一直是objc中得一个重点和难点
这里说一些自己的理解
首先讲一下retain,即对receiver的保留,仅仅使其refcount+1
以NSString对象为例
在讨论引用计数之前必须声明清楚如NSString*str = @“1234”;这类存储在静态存储区的内存没有引用计数这个概念即refcount对其是没有意义的。
如下例子
NSString*str = [NSString stringWithFormat:@"hello"];
此时str 的refCount为1
NSString* retainStr = [str retain];
此时str与retainStr指向同一块内存,并且他们的refcount都为2
这个例子说明retain只是做了指针的拷贝,并无做内容拷贝亦即c/c++里所说的浅拷贝
不过objc中比C++中更安全,原因如下
在C++中如果对str所指向的内存进行release,那块内存就会被销毁,在去使用str或者retainStr都将使程序出现莫名的错误。
在objc中如果对str所指向的内存进行release,那块内存不会被销毁,因为还有retainStr指向了那块内存,这个时候使用str和retainStr都将是安全的。
再者讲一下copy,讲到copy还必须要讲到mutableCopy
copy即对receiver的拷贝,但是copy比retain得情况要复杂一些,因为有些时候copy的意义和retain一样,只是使refcount+1,而有时并不会使refcount+1,而是对对象内存块的深拷贝。
举例说明
NSString*str = [NSString stringWithFormat:@"hello"];
此时str 的refCount为1,这个肯定没问题。
NSString *copyStr = [str copy];
在这中情况下str与copyStr指向同一块内存,并且他们的refcount都为2即如上说的和retain的意义一样。并没有为copyStr复制新的内容。
然而
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"123"];
NSString *copyStr = [s copy];
在这种情况下copyStr指向的内存块与str是不同的,copy函数为str那块内存做了拷贝,并且将新内存的地址赋给copyStr,此时str与copyStr的refcount都是1.
出现这种情况的原因,我的理解是因为str指向可变字符串,而copyStr指向的是不可变字符串,这个时候编译器为copyStr分配了一块新的内存。
NSString *str = [NSString stringWithFormat:@"hello"];
NSmutable *String*mcopyStr = [str mutableCopy];
NSMutableString*str = [[NSMutableString alloc] initWithFormat:@"123"];
NSMutableString *copyStr= [s mutableCopy];
以上两种情况也和上面的现象一样,是深拷贝。
结论:1.向NSString对象发送copy消息,这时候copy和retain的意义是一样的
2.向NSMutableString对象发送copy,此时是深度拷贝
3.向NSString/NSMutableString对象发送mutableCopy,此时是深度拷贝
总结以上三个结论可以得出以下两个结论
1.对于不定字符串,系统在进行copy/mutableCopy都会分配新的内存块(即深拷贝)
2.对于固定字符串发送copy,这个时候是浅拷贝,发送mutableCopy是深拷贝。