Deep copy and shallow copy of IOS collection
Archives
iOS
Concept
There are two ways to copy objects: Shallow copy and deep copy. As the name implies, shallow copy, not copy the object itself, just copy the pointer to the object; Deep copy copies the entire object memory directly into another memory.
A picture of the
It is simpler to say: Shallow copy is pointer copy, deep copy is content copy.
Shallow copy of collection (shallow copy)
There are many ways to shallow copy a collection. When you make a shallow copy, the retain message is sent to the original collection, the reference count plus 1, and the pointer is copied to the new collection.
Now let's look at some examples of shallow replication:
NSArray *shallowCopyArray = [someArray copyWithZone:nil];
NSSet *shallowCopySet = [NSSet mutableCopyWithZone:nil];
NSDictionary *shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:NO];
Deep copy of the collection
There are two methods for deep copy of a collection. You can use Initwitharray:copyitems: Set the second parameter to Yes to deep copy, as
NSDictionary shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:YES];
If you copy deep in this way, each object in the collection will receive a copywithzone: message. If the object in the collection follows the Nscopying protocol, the object is deeply copied to the new collection. If an object does not follow the Nscopying protocol and attempts to make a deep copy in this way, an error occurs at run time. Copywithzone: This copy can only provide a single layer of memory copy (One-level-deep copy), rather than a true deep copy.
The second method is to archive the collection (archive) and then extract the files (unarchive), such as:
NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
Single-layer deep copy of the collection (One-level-deep copy)
See here, there are alumni asked: If in a multilayer array, the first layer of the content copy, the other layer for pointer copy, this case is a deep copy, or shallow copy? On this, Apple official website document has such a sentence description
This kind of copy are only capable of producing a one-level-deep copy. If you are only need a one-level-deep copy ...
If you need a true deep copy, such as when you have an array of arrays ...
As can be seen from the text, Apple believes that this duplication is not a true deep copy, but rather it is called a single-layer deep copy (one-level-deep copy). Therefore, the concept of shallow copy, deep copy, and single layer deep copy is differentiated by some people on the Internet.
- Shallow copy (shallow copy): During a shallow copy operation, the pointer is copied for each layer of the copied object.
- Deep copy (One-level-deep copy): In a deep copy operation, at least one layer of the copied object is a deep copy.
- Full replication (real-deep copy): During a full copy operation, object replication is for each layer of the replicated object.
Of course, these are all conceptual things, and there's no need to dwell on this. As long as the copy operation is known, the pointer or the content is copied.
Copy and Mutablecopy Methods for system objects
Whether it is a collection class object or a non-collection class object, the following guidelines are followed when you receive copy and Mutablecopy messages:
- Copy returns the Imutable object, so if the Mutable object interface is used for the copy return value, it will be crash;
- Mutablecopy returns the Mutable object;
The following is a detailed description of the copy and Mutablecopy methods for non-collection class objects and collection class objects
1. Copy and mutablecopy of non-collection objects
System non-Collection class object refers to NSString, nsnumber ... Objects such as the. Let's look at an example of a non-aggregate class immutable object copy.
-
nsstring *string = @
-
nsstring *= [string
-
nsmutablestring *= [string
By looking at the memory, you can see that the address of stringcopy and string is the same, the pointer is copied, and the address of stringmcopy is not the same as the string, the content is copied;
Look again at the Mutable object copy Example
NSMutableString *string = [NSMutableString stringWithString: @"origin"];
//copy
NSString *stringCopy = [string copy];
NSMutableString *mStringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
//change value
[mStringCopy appendString:@"mm"]; //crash
[string appendString:@" origion!"];
[stringMCopy appendString:@"!!"];
Running the above code is crash on line 7th, because the object returned by copy is the immutable object. Note the 7th line after the run, look at the memory, found that the string, Stringcopy, Mstringcopy, stringmcopy four objects memory address is different, indicating that this is a copy of the content.
With two examples, we can draw the conclusion that:
In a non-collection class object: Copy the Immutable object, copy the pointer, copy the contents of the mutablecopy operation, and copy and mutablecopy the Mutable object as content replication. The code is simply represented as follows:
- [Immutableobject Copy]//Shallow copy
- [Immutableobject mutablecopy]//Deep copy
- [Mutableobject Copy]//Deep copy
- [Mutableobject mutablecopy]//Deep copy
2. Copy and Mutablecopy of the collection class object
The collection class object refers to Nsarray, Nsdictionary, Nsset ... Objects such as the. Here's an example of a collection class immutable object using Copy and Mutablecopy:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
Viewing the content, you can see that the Copyarray and array addresses are the same, and the addresses of the Mcopyarray and array are different. The copy operation has a copy of the pointer, and mutablecopy copies the content. However, it should be emphasized that the copy of the content here is simply a copy of the array object, and the elements inside the array collection are still pointer copies. This is quite similar to the copy of the non-collection immutable object above, so will the copy of the Mutable object be similar? Let's go down and look at examples of mutable object copies:
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
Look at the memory, as we expected, Copyarray, Mcopyarray, and array memory addresses are different, indicating that Copyarray, Mcopyarray have a content copy of the array. Again, we can draw the conclusion that:
In the collection class object, copy the immutable object, which is the pointer copy, the mutablecopy is the content copy, and the copy and Mutablecopy of the Mutable object are content replication. However: the content copy of the collection object is limited to the object itself, and the object element is still a pointer copy. The code is simply represented as follows:
- [Immutableobject Copy]//Shallow copy
- [Immutableobject mutablecopy]//single layer deep copy
- [Mutableobject Copy]//single layer deep copy
- [Mutableobject mutablecopy]//single layer deep copy
This code conclusion is very similar to the non-collection class.
At this time, is not someone to ask, if you want to copy elements of the collection object what to do? Students with this question may wish to look back at the deep copy of the collection.
Well, deep copy and shallow copy are here.
In the process of collecting data, we can find a point that is likely to make a mistake.
NSString *str = @"string";
str = @"newString";
The above code, after executing the second line of code, the memory address changed. At first glance, it was a bit of an accident. According to the C language experience, after initializing a string, the first address of the string is determined, and no matter how the string content is modified, the address will not change. But the second line here is not a re-assignment of the memory address pointed to by STR, because the left str of the assignment operator is a pointer, which means that the memory address is modified here.
So the second line should understand this: "Newstirng" as a new object, the memory address of this object is assigned to Str.
I like the next two ways to view memory address
p str
Prints the memory address and object contents of the object itself
(lldb) p str
(NSString *) $0 = 0x000000010c913680 @"a"
po &str
The address where the pointer to the referenced object is printed
(lldb) po &str
0x00007fff532fb6c0
Deep copy and shallow copy of IOS collection