Deep copy and shallow copy this question is often asked in the interview, and in the actual development, as long as the slightest careless, there will be problems here. Especially for beginners, it is necessary for us to study this concept carefully. I'll show you the actual code, and the sample code is uploaded here.
The first sentence to explain: a deep copy is a copy of the content, a shallow copy is a pointer copy.
A deep copy is a new object that copies the same value as the original, but has a completely different memory address, and does not have any relationship with the original object after it is created. A shallow copy is a pointer to the original object, so that the reference count of the original object is +1, which can be understood as creating a new pointer to the original object, and not creating a completely new object.
(1) deep copy, shallow copy of non-container class object
The string is directly assigned, and if it is copy on the right, it is a shallow copy, and the right side, if it is mutablecopy, is a deep copy. nsstring *string1 = @ "HelloWorld"; NSString *string2 = [string1 copy]; Shallow copy nsstring *string3 = [string1 mutablecopy];//Deep copy nsmutablestring *string4 = [string1 copy];//Shallow copy NSM utablestring *string5 = [string1 mutablecopy]; Deep copy NSLog (@ "string1 =%d;string2 =%d", string1,string2); NSLog (@ "string1 =%d;string3 =%d", string1,string3); NSLog (@ "string1 =%d;string4 =%d", String1,string4); NSLog (@ "string1 =%d;string5 =%d", string1,string5);
The printing results are as follows:
。
Here I am using%d format to print out the memory address of the string object. I mainly use memory address to determine whether it is a deep copy or a shallow copy, in this case, whether it is a deep copy or a shallow copy, the value of the string object is the same, so for the time being does not print the value, and only print the address. The original string here is directly assigned, you can find that the right side if you use copy, then the printed memory address is the same, indicating that it is a shallow copy, only the pointer to the original object is copied, not create a new object. If you use Mutablecopy on the right, the print out of a different memory address means that a new object is created and a deep copy.
Simply explain what non-container class objects are, such as nsstring,nsnumber, which cannot contain other objects called non-container classes. such as Nsarray and Nsdictionary can accommodate other objects called container class objects.
To make a small summary:
--Shallow copy similar to retain, reference counting object +1. Create a pointer;
Deep copy is a true copy and a new object is created. The Copy property represents the same content for two objects, the new object retain to 1, independent of the reference count of the original object, and the original object has not changed. Copy reduces the object's dependency on the context.
--The Retain property indicates that two objects have the same address (creating a pointer, pointer copy), and the contents are of course the same, the retain value of this object is +1. That is, retain is a pointer copy, copy is a copy of the content.
(2) Changing the way strings are created, using stringWithFormat to create strings instead of directly assigning values
The result is ibid. If copy is on the right, then it is a shallow copy, and if it is mutablecopy on the right, it is a deep copy. nsstring *string1 = [NSString stringwithformat:@ "HelloWorld"]; NSString *string2 = [string1 copy]; Shallow copy nsstring *string3 = [string1 mutablecopy];//Deep copy nsmutablestring *string4 = [string1 copy];//Shallow copy NSM utablestring *string5 = [string1 mutablecopy]; Deep copy NSLog (@ "string1 =%d;string2 =%d", string1,string2); NSLog (@ "string1 =%d;string3 =%d", string1,string3); NSLog (@ "string1 =%d;string4 =%d", String1,string4); NSLog (@ "string1 =%d;string5 =%d", string1,string5);
The printing results are as follows:
。
Results same as (1). Because they are immutable strings, the way they are created does not affect how they are copied. So it can be concluded that for non-container class objects such as strings, copy is a shallow copy and mutable is a deep copy.
(3) The above tests are immutable strings, here to try the variable string
If it is a mutablestring, a new object will be created, either copy,mutablecopy. nsmutablestring *string1 = [nsmutablestring stringwithstring:@ "HelloWorld"]; NSString *string2 = [string1 copy]; Deep copy nsstring *string3 = [string1 mutablecopy];//Deep copy nsmutablestring *string4 = [string1 copy];//Deep copy NSM utablestring *string5 = [string1 mutablecopy]; Deep copy NSLog (@ "string1 =%d;string2 =%d", string1,string2); NSLog (@ "string1 =%d;string3 =%d", string1,string3); NSLog (@ "string1 =%d;string4 =%d", String1,string4); NSLog (@ "string1 =%d;string5 =%d", string1,string5);
The printing results are as follows:
。
As you can see, for mutablestring, the right side, either copy or Mutablecopy, creates a new object that belongs to the deep copy.
Now let's make a little change to the above code:
If it is a mutablestring, a new object will be created, either copy,mutablecopy. nsmutablestring *string1 = [nsmutablestring stringwithstring:@ "HelloWorld"]; NSString *string2 = [string1 copy]; Deep copy nsstring *string3 = [string1 mutablecopy];//Deep copy nsmutablestring *string4 = [string1 copy];//Deep copy NSM utablestring *string5 = [string1 mutablecopy]; Deep copy NSLog (@ "string1 =%d;string2 =%d", string1,string2); NSLog (@ "string1 =%d;string3 =%d", string1,string3); NSLog (@ "string1 =%d;string4 =%d", String1,string4); NSLog (@ "string1 =%d;string5 =%d", string1,string5); Add the following code [String4 appendstring:@ "Mmmmmm"]; [String5 appendstring:@ "11111"]; NSLog (@ "String4 =%@", String4); NSLog (@ "string5 =%@", string5);
I've added four lines of code, and I want to check if the string returned is mutable after copy and mutablecopy are executed on a mutable string. At the same time, in order to check which line appears crash, I hit an unexpected breakpoint in advance. There is appendstring method for nsmutablestring, and NSString has no appendstring method, so this test should be no problem. After running the code, it will be [String4 apendstring:@ "MMMMM"]; this line crashes. After practical testing, the following conclusions can be drawn:
-For the replication of mutable objects, it is a deep copy;
--The object returned after a Mutable object copy is immutable, and the object returned after Mutablecopy is mutable.
(4) We mentioned above are the system class, if it is our custom class, copy the result? I define a person class below, which is implemented as follows:
Person.h
#import <Foundation/Foundation.h> @interface person:nsobject@property (nonatomic, copy) NSString *name;@ Property (Nonatomic, assign) Nsinteger age; @end
Person.m
#import "Person.h" @interface person () <nscopying, nsmutablecopying> @end @implementation person//corresponding to the Copy method-(ID) Copywithzone: (Nszone *) zone{person *person = [[Person Allocwithzone:zone] init]; Person.name = Self.name; The self here is the object of copy person.age = self.age; return person;} -(ID) Mutablecopywithzone: (Nszone *) zone{person *person = [[Person Allocwithzone:zone] init]; Person.name = Self.name; Person.age = Self.age; return person;} @end
First of all, why do you want to implement the Copywithzone and Mutablecopywithzone methods described above? In fact, not all of the objects in iOS support the copy, Mutablecopy method, only the class that adheres to the Nscopying protocol can send a copy message, and the class that adheres to the Nsmutablecopying protocol can send a mutablecopy message. Otherwise it will crash. We can easily use the Copy,mutablecopy method in the system class, because the system classes themselves implement the Nscopying,nsmutablecopy protocol, and you can access the interface document for viewing.
Then write the test code as follows:
The person class must implement the Copywithzone and Mutablecopywithzone methods. Person *person = [[Person alloc] init]; Person.name = @ "Jack"; Person.age =; Person *copyperson = [person copy]; Deep copy person *mutablecopyperson = [person mutablecopy];//Deep copy NSLog (@ "person =%d;copyperson =%d", PERSON,COPYP Erson); NSLog (@ "person =%d;mutablecopyperson =%d", Person,mutablecopyperson);
The printing results are as follows:
。
You can see that both copy and Mutablecopy create a new object after copying. Why is it? Because we were in Copywithzone: A new object was created in the Mutablecopywithzone method, so it's not surprising at all.
(5) from the above (4) can see my person custom object after copy is the creation of a completely new object, then the properties of this object? Are these properties deep or shallow copies?
nsmutablestring *othername = [[Nsmutablestring alloc] initwithstring:@ "Jack"]; Person *person = [[Person alloc] init]; Person.name = Othername; Person.age =; [Othername appendstring:@ "and Mary"]; NSLog (@ "person.name =%@", person.name);
The printing results are as follows:
。
The result is "Jack" instead of "Jack and Mary". Description in the execution of person.name = Othername, when a string was recreated. But please note that the property modifier for my name here is copy, what happens if I change copy to strong?
Yes, right, the answer is "Jack and Mary" after the name is changed to strong. So here we can draw the following small conclusions:
-Because the othername here is mutable, the Person.name property is copy, so a new string is created, which belongs to the deep copy;
-If Person.name is set to strong, then it is a shallow copy. Because strong will hold the original object, so that the reference count of the original object +1, is actually a pointer copy.
--of course, the strong or copy here depends on the actual demand.
(6) similar to the above (5), I now modify the code as follows:
NSString *othername = @ "Jack"; Person *person = [[Person alloc] init]; Person.name = Othername; Person.age =; NSLog (@ "othername =%d;person.name =%d", othername,person.name);
In fact, it is very well understood, whether person.name is strong or copy, is a pointer copy. All points to the memory address of the othername.
Now modify the code as follows:
NSString *othername = @ "Jack"; Person *person = [[Person alloc] init]; Person.name = [othername copy]; Person.age =; NSLog (@ "othername =%d;person.name =%d", othername,person.name);
Similarly, whether Person.name is a strong or copy, it is a pointer copy. All points to the memory address of the othername. Since copy is generally a shallow copy of immutable objects, this is fine.
Modify the code again as follows:
NSString *othername = @ "Jack"; Person *person = [[Person alloc] init]; Person.name = [Othername mutablecopy]; Person.age =; NSLog (@ "othername =%d;person.name =%d", othername,person.name);
Whether Person.name is a strong or copy, it is a copy of the content. Create an entirely new object. Because performing mutablecopy on immutable objects is generally a deep copy, there is no problem.
(7) Speaking of so many non-container objects, finally we talk about the container object array. The immutable container object is first spoken
Nsarray *array01 = [Nsarray arraywithobjects:@ "a", @ "B", @ "C", nil]; Nsarray *copyarray01 = [array01 copy]; Nsmutablearray *mutablecopyarray01 = [Array01 mutablecopy]; NSLog (@ "array01 =%d,copyarray01 =%d", array01,copyarray01); NSLog (@ "array01 =%d,mutablecopyarray01 =%d", array01,mutablecopyarray01); NSLog (@ "array01[0] =%d,array01[1] =%d,array01[2] =%d", array01[0],array01[1],array01[2]); NSLog (@ "copyarray01[0] =%d,copyarray01[1] =%d,copyarray01[2] =%d", copyarray01[0],copyarray01[1],copyarray01[2]); NSLog (@ "mutablecopyarray01[0] =%d,mutablecopyarray01[1] =%d,mutablecopyarray01[2] =%d", mutablecopyarray01[0], MUTABLECOPYARRAY01[1],MUTABLECOPYARRAY01[2]);
The printing results are as follows:
。
We can draw the following conclusions:
--CopyArray01 and Array01 point to the same object, including the elements that are also pointing to the same pointer.
--MutableCopyArray01 and Array01 point to different objects, but the elements in them point to the same object, MutableCopyArray01 can modify their own objects.
--COPYARRAY01 is a pointer to array01 copy (shallow copy), while MUTABLECOPYARRAY01 is content replication.
--------------------------------------------------------------------------------------------------------------- -------------------------------------------------------make a split line.
Above is the immutable container nsarray, here test the variable container nsmutablearray:
Nsmutablearray *array01 = [Nsmutablearray arraywithobjects:@ "a", @ "B", @ "C", nil]; Nsarray *copyarray01 = [array01 copy]; Nsmutablearray *mutablecopyarray01 = [Array01 mutablecopy]; NSLog (@ "array01 =%d,copyarray01 =%d", array01,copyarray01); NSLog (@ "array01 =%d,mutablecopyarray01 =%d", array01,mutablecopyarray01); NSLog (@ "array01[0] =%d,array01[1] =%d,array01[2] =%d", array01[0],array01[1],array01[2]); NSLog (@ "copyarray01[0] =%d,copyarray01[1] =%d,copyarray01[2] =%d", copyarray01[0],copyarray01[1],copyarray01[2]); NSLog (@ "mutablecopyarray01[0] =%d,mutablecopyarray01[1] =%d,mutablecopyarray01[2] =%d", mutablecopyarray01[0], MUTABLECOPYARRAY01[1],MUTABLECOPYARRAY01[2]);
The results are printed as follows:
。
The conclusions may be as follows:
--Similar to container objects and non-container objects, Variable object copy (Copy,mutablecopy) is a new object, immutable object copy is shallow copy, mutablecopy is deep copy.
--For a container, the element object is always a pointer copy.
The above is only part of, want to deep copy, shallow copy have more in-depth understanding, must first of memory management is more familiar with, and then in the actual development to practice constantly, will be arbitrary.
iOS development-deep copy and shallow copy