Shallow copy and deep copy in Objective-c

Source: Internet
Author: User








Shallow copy



A shallow copy is a copy of the memory address, so that the target object pointer and source object point to the same piece of memory space. Such as:



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


A shallow copy is simply a simple copy of the object, allowing several objects to share a piece of memory, and when the memory is destroyed, several pointers to the memory need to be redefined before they can be used, or they will become wild pointers.


A shallow copy inside IOS:



In IOS, using the Retain keyword for reference counting is a more insured, shallow copy. He allows a few pointers to share the same memory space, but also in release due to the existence of the count, will not be easy to destroy the memory, to achieve a more simple use.



Deep copy:



Deep copy refers to the specific contents of the Copy object, and the memory address is self-allocated, after the end of the copy, two objects, although the value is the same, but the memory address is not the same, two objects do not affect each other, non-interference.



The difference between copy and retain:



Copy is to create a new object, retain is to create a pointer, reference the object Count plus one. The Copy property identifies two objects with the same contents, the new object retain count is 1, independent of the old object reference count, and the old object does not change. Copy reduces the object's dependency on the context.



Deep copy in iOS:



iOS provides copy and Mutablecopy methods, as the name implies, copy is copying a Imutable object, and Mutablecopy is copying a mutable object. Here are a few examples to illustrate.
This refers to objects such as NSString, NSNumber, and so on.


NSString *string = @”dddd";
NSString *stringCopy = [string copy];
NSMutableString *stringDCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];



View memory you can see that the string and stringcopy point to the same piece of memory area (weak reference), and the reference count has not changed. And Stringmcopy is what we call the true meaning of replication, the system allocates a new memory for it, is two separate string content is the same.


Copy construction:



Of course not all objects in iOS support Copy,mutablecopy, classes that follow the Nscopying protocol can send copy messages, and classes that follow the Nsmutablecopying protocol can send mutablecopy messages.



If a copy or mutablecopy is sent without complying with the appeal agreement, an exception will occur. However, the default iOS class does not follow these two protocols. If you want to customize copy then you must obey Nscopying and implement Copywithzone: method, if you want to customize mutablecopy then you must obey Nsmutablecopying, and implement Mutablecopywithzone: Method.



If it is the object we define, then we have to implement nscopying ourselves, nsmutablecopying so that we can invoke copy and Mutablecopy. As an example:



@interface MyObj : NSObject<NSCopying, NSMutableCopying>{
    NSMutableString *_name;
    NSString * _imutableStr ;
    int _age;
}     
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *imutableStr;
@property (nonatomic) int age;


Copy Copy construction:




- (id)copyWithZone:(NSZone *)zone{
    MyObj *copy = [[[self class] allocWithZone :zone] init];
    copy->name = [_name copy];
    copy->imutableStr = [_imutableStr copy];
    copy->age = age;
    return copy;
}

Mutablecopy Copy Construction:


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


Before reading this article, we first understand the difference between copy and retain, if there is an incorrect place, we would like to advise you:



The difference between copy and retain:



Copy is to create a new object, retain is to create a pointer to reference the object Count plus 1. The Copy property represents the same contents as two objects, the new object retain to 1, independent of the reference count of the old object, and the old object does not change. Copy reduces the object's dependency on the context.



The Retain property indicates that two objects have the same address (creating a pointer, copy of the pointer) and, of course, the same content, the retain value of this object +1 that is, retain is a pointer copy, copy is a copy of the content.






Of course not all objects in iOS support Copy,mutablecopy, classes that follow the Nscopying protocol can send copy messages, and classes that follow the Nsmutablecopying protocol can send mutablecopy messages. If a copy or mutablecopy is sent without complying with the appeal agreement, an exception will occur. However, the default iOS class does not follow these two protocols. If you want to customize copy then you must obey Nscopying and implement Copywithzone: method, if you want to customize mutablecopy then you must obey Nsmutablecopying, and implement Mutablecopywithzone: Method.



First, we need to have such a premise:
[Array addobject:obj];
This will increase the reference count of obj by 1, and if you use remove, the reference count of obj will be reduced by one.
This is how iOS handles collections in memory.
So, suppose that obj is only owned by an array:
ID temp = [array objectatindex:0];
[Array removeobjectatindex:0];
If you want to use temp again, it will go wrong, because obj has been released at this time.
(Note that if you test with nsstring, be aware that @ "ABC" is a constant:-) )
Because in the program often encounters the collection class The pass value, therefore, the simple retain may not suffice, needs to the collection content copy, namely deep copy.
Let's talk about it here.
iOS provides copy and Mutablecopy methods, as the name implies, copy is copying a Imutable object, and Mutablecopy is copying a mutable object. Here are a few examples to illustrate.
1. Non-container class objects of the system
This refers to objects such as Nsstring,nsnumber and so on.
NSString *string = @ "Origion";
NSString *stringcopy = [string copy];
Nsmutablestring *stringmcopy = [string mutablecopy];
[Stringmcopy appendstring:@ "!!"];
View memory you can see that string and stringcopy point to the same chunk of memory (also known as Apple's weak reference weak reference), at which point the reference count of Stringcopy is 2 of the same as string. And Stringmcopy is what we call the true meaning of replication, the system allocates new memory to it, but the pointer points to the same string as it refers to.
Let's look at the following example:
nsmutablestring *string = [nsmutablestring stringwithstring: @ "origion"];
NSString *stringcopy = [string copy];
Nsmutablestring *mstringcopy = [string copy];
Nsmutablestring *stringmcopy = [string mutablecopy];
[Mstringcopy appendstring:@ "MM"];//error
[String appendstring:@ "origion!"];
[Stringmcopy appendstring:@ "!!"];
The memory allocated by the above four NSString objects is not the same. But for Mstringcopy is actually a imutable object, so the above will be an error.
For non-container class objects of the system, we can assume that if copying an immutable object, copy is pointer copy (shallow copy) and mutablecopy is the object copy (deep copy). If it is a copy of a mutable object, it is a deep copy, but the object returned by copy is immutable.
2. System's container class object
Refers to nsarray,nsdictionary and so on. For the container class itself, the conclusions discussed above are also applicable, and it is necessary to explore the changes of objects in the container after replication.
Copy returns an immutable object, Mutablecopy returns a Mutable object
Nsarray *array1 = [Nsarray arraywithobjects:@ "a", @ "B", @ "C", nil];
Nsarray *arraycopy1 = [array1 copy];
ArrayCopy1 is the same Nsarray object as the array (pointing to the same object), including the elements inside the array that also point to the same pointer
NSLog (@ "Array1 retain count:%d", [array1 Retaincount]);
NSLog (@ "Array1 retain count:%d", [arrayCopy1 Retaincount]);
Nsmutablearray *marraycopy1 = [Array1 mutablecopy];
MArrayCopy1 is a mutable copy of Array1, which points to different objects and array1, but the elements in them and the elements in the array1 point to the same object. MArrayCopy1 can also modify their own objects
[MArrayCopy1 addobject:@ "de"];
[MArrayCopy1 removeobjectatindex:0];
Array1 and ArrayCopy1 are pointer copies, and MARRAYCOPY1 is an object copy, and mArrayCopy1 can also change elements in the period: delete or Add. Note, however, that the element content inside the container is a pointer copy.
Let's test it with another example.
Nsarray *marray1 = [Nsarray arraywithobjects:[nsmutablestring stringwithstring:@ "A"],@ "B", @ "C", nil];
Nsarray *marraycopy2 = [mArray1 copy];
NSLog (@ "MArray1 retain count:%d", [MArray1 Retaincount]);
Nsmutablearray *marraymcopy1 = [MArray1 mutablecopy];
NSLog (@ "MArray1 retain count:%d", [MArray1 Retaincount]);
Marraycopy2,marraymcopy1 and MArray1 point to different objects, but the elements are the same object--the same pointer
A little bit of testing.
nsmutablestring *teststring = [MArray1 objectatindex:0];
TestString = @ "1a1";//This will change the teststring pointer, in fact, the @ "1a1" temporary object is assigned to TestString
[TestString appendstring:@ "tail"];//so that the first element of the above three arrays has been changed
Thus, for a container, its element object is always a pointer copy. If you need an element object that is also an object copy, you need to implement a deep copy. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/collections/articles/copying.html
Nsarray *array = [Nsarray arraywithobjects:[nsmutablestring stringwithstring:@ "First"],[nsstringstringwithstring:@ " B "],@" C ", nil];
Nsarray *deepcopyarray=[[nsarray alloc] Initwitharray:array Copyitems:yes];
nsarray* Truedeepcopyarray = [Nskeyedunarchiver unarchiveobjectwithdata:
[Nskeyedarchiver Archiveddatawithrootobject:array]];
Truedeepcopyarray is a deep copy of the full sense, while Deepcopyarray is not, for the immutable elements within the Deepcopyarray it is the pointer copy. Or our own way of implementing deep copies. Because if an element of the container is immutable, the object remains unchanged after you copy it, so you only need to copy the pointer. The pointer copy is sufficient unless you re-assign the elements inside the container. For example, [[Array objectatindex:0]appendstring:@ ' SD '] other objects in the container will not be affected. [[Array objectatindex:1] and [[Deepcopyarray objectatindex:0] even point to the same block of memory, but we have no way to modify it-because it is immutable. So the pointer copy is sufficient. So this is not a deep copy of the full meaning, but Apple's official document has listed it as deeply copy, and has added a copy and mutablity relationship description, so do a note here (there is a little doubt, there is understanding of the enlighten AH).
Or our own way of implementing deep copies (slightly).
3. Custom Objects
If it is the object we define, then we have to implement nscopying,nsmutablecopying ourselves so that we can invoke copy and Mutablecopy. As an example:
@interface myobj:nsobject<nscopying,nsmutablecopying>
{
Nsmutablestring *name;
NSString *imutablestr;
int age;
}
@property (nonatomic, retain) nsmutablestring *name;
@property (nonatomic, retain) NSString *imutablestr;
@property (nonatomic) int age;
@end
@implementation MYOBJ
@synthesize name;
@synthesize age;
@synthesize Imutablestr;
-(ID) init
{
if (self = [super init])
{
Self.name = [[nsmutablestring alloc]init];
SELF.IMUTABLESTR = [[NSString alloc]init];
Age =-1;
}
return self;
}
-(void) dealloc
{
[Name release];
[Imutablestr release];
[Super Dealloc];
}
-(ID) Copywithzone: (Nszone *) zone
{
MYOBJ *copy = [[[Self class] allocwithzone:zone] init];
Copy->name = [name copy];
COPY-&GT;IMUTABLESTR = [imutablestr copy];
Copy->name = [name Copywithzone:zone];;
COPY-&GT;IMUTABLESTR = [Name copywithzone:zone];//
Copy->age = age;
return copy;
}
-(ID) Mutablecopywithzone: (Nszone *) zone
{
MYOBJ *copy = Nscopyobject (self, 0, zone);
Copy->name = [Self.name mutablecopy];
Copy->age = age;
return copy;
}


Shallow copy and deep copy in Objective-c


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.