Deep and shallow copies in the Objective-c

Source: Internet
Author: User



The copies between objects in the objective-c are divided into shallow and deep copies. Plainly, a shallow copy of a non-container class is the address of the copied object, and the contents of the object are still a copy, and no new memory is allocated. A deep copy of a non-container class is a rewrite of the allocated memory, and then the contents of the other object are left intact for me. A deep copy of a container class is a copy of every element in the container, and a shallow copy of the container class is not a copy of the contents of the container, the address of the two containers is different, but the container is the same, and the value is changed in one container, and the value in the other shallow copy container changes. So for non-container classes to see whether the object is a deep copy or a shallow copy to see the memory address of the object can be seen, and for the container class, we further look at the contents of the container. Because OC uses reference counting as a way to manage memory, we can also analyze whether deep or shallow copies of objects are retaincount by observing the changes in the object's change. The following is a detailed understanding of the object's deep and shallow copies by testing different types of objects.



So what types of objects are generally divided into? From the perspective of mutable immutable and container class non-container classes, you can divide objects into several types, so what is a container class? The container class is the object declared with the class that can accommodate other objects, and non-container classes do not have these functions. So what is mutable or immutable? Variable when the size of the memory can be changed according to needs, and immutable is allocated after the allocation is not able to change his memory space (the above is my understanding, insufficient or understand the bias of the place also please criticize, reproduced this article please indicate the source)



1. Non-container immutable objects, such as NSString



2. Non-container mutable objects: such as Nsmutablestring



3. Container class immutable objects: such as Nsarray



4. Container Class Mutable objects: such as Nsmutablearray



Before you look at the shades of a copy, you need to know the characteristics of retain,copy and Mutablecopy, features as follows:



1.retain: Always shallow copy. The reference count is added one at a time. Returns whether the object is mutable and consistent with the object being copied.



2.copy: The reference count does not change for a deep copy of a mutable object, and for an immutable object is a shallow copy, the reference count is added one at a time. Always returns an immutable object.



3.mutableCopy: Always deep copy, reference count does not change. Always returns a Mutable object.



Below the container non-container, variable non-mutable combination of retain,copy,mutablecopy to carefully analyze the OC in the depth of the copy, Code walk:












1. For non-container class immutable objects retain and copy is a shallow copy, Mutablecopy is a deep copy



2. The address of the object obtained by the shallow copy is the same as the address of the original object



3. A deep copy returns a new memory address, and the returned object is a Mutable object








1.retian pair of variable objects for shallow copy



2.copy non-container class for mutable objects is a deep copy



3.mutableCopy to variable non-container class for deep copy



3. Container class + non-mutable object + retain + copy + mutablecopy



under the test of non-mutable objects of the container class, the running result of the program shows that when using Mutablecopy, a new container is actually returned (as seen by the memory address), but the container object is a deep copy of the container, but the element from the output container is a shallow copy of the container. So how do we implement a full copy of the container? The following is described below.



 The code is as follows:



NSMutableString * string = [NSMutableString stringWithFormat: @ "ludashi"];
    // The second kind: immutable object copy of container class
    NSLog (@ "Container class immutable object copy");
    NSArray * array = [NSArray arrayWithObjects: string, @ "b", nil];
    NSLog (@ "array [0] =% @, init_array.retainCount =% d", array [0], (int) array.retainCount);
    
    // Assign array to array1 by retain method
    NSArray * array1 = [array retain];
    NSLog (@ "array1 [0] =% @, retain_array1.retainCount =% d", array1 [0], (int) array1.retainCount);
    
    // Assign array to array2 by copy
    NSArray * array2 = [array copy];
    NSLog (@ "array2 [0] =% @, copy_array.retainCount =% d", array2 [0], (int) array2.retainCount);
    
    // Assign array to array3 by mutableCopy
    NSArray * array3 = [array mutableCopy];
    NSLog (@ "array3 [0] =% @, mutableCopy_array3.retainCount =% d", array3 [0], (int) array3.retainCount);
    
    // output each address separately
    NSLog (@ "output each address separately");
    NSLog (@ "array_p =% p", array);
    NSLog (@ "array1_p =% p", array1);
    NSLog (@ "array2_p =% p", array2);
    NSLog (@ "array3_p =% p", array3);
    
    // output each address separately
    NSLog (@ "respectively output the address of the first element in the copied array");
    NSLog (@ "array_p [0] =% p", array [0]);
    NSLog (@ "array1_p [0] =% p", array1 [0]);
    NSLog (@ "array2_p [0] =% p", array2 [0]);
    NSLog (@ "array3_p [0] =% p", array3 [0]);

Run Result:


2014-08-13 15: 24: 57.386 Memory [3678: 303] Container class immutable object copy
2014-08-13 15: 24: 57.386 Memory [3678: 303] array [0] = ludashi, init_array.retainCount = 1
2014-08-13 15: 24: 57.387 Memory [3678: 303] array1 [0] = ludashi, retain_array1.retainCount = 2
2014-08-13 15: 24: 57.387 Memory [3678: 303] array2 [0] = ludashi, copy_array.retainCount = 3
2014-08-13 15: 24: 57.387 Memory [3678: 303] array3 [0] = ludashi, mutableCopy_array3.retainCount = 1
2014-08-13 15: 24: 57.388 Memory [3678: 303] outputs each address separately
2014-08-13 15: 24: 57.388 Memory [3678: 303] array_p = 0x1005001b0
2014-08-13 15: 24: 57.388 Memory [3678: 303] array1_p = 0x1005001b0
2014-08-13 15: 24: 57.389 Memory [3678: 303] array2_p = 0x1005001b0
2014-08-13 15: 24: 57.389 Memory [3678: 303] array3_p = 0x100107750
2014-08-13 15: 24: 57.389 Memory [3678: 303] outputs the address of the first element in the array after copying
2014-08-13 15: 24: 57.390 Memory [3678: 303] array_p [0] = 0x100500040
2014-08-13 15: 24: 57.390 Memory [3678: 303] array1_p [0] = 0x100500040
2014-08-13 15: 24: 57.390 Memory [3678: 303] array2_p [0] = 0x100500040
2014-08-13 15: 24: 57.390 Memory [3678: 303] array3_p [0] = 0x100500040





4. Container class + Variable object + retain + copy + mutablecopy



tested against mutable objects of the container class, copy and mutablecopy are deep copies of the container itself because a new container address is returned, but the element in the container is still a shallow copy.



The code is as follows:


NSLog (@ "************************************************ \ n \ n \ n ");
    // Fourth: a copy of the variable object of the container class, implemented using NSMutableArray
    NSLog (@ "Copy of mutable object of container class");
    
    
    
    NSMutableArray * m_array = [NSMutableArray arrayWithObjects: string, nil];
    NSLog (@ "m_array [0] =% @, init_m_array_retainCount =% d", m_array [0], (int) m_array.retainCount);
    
    // Assign m_array to retain_m_array1
    NSMutableArray * m_array1 = [m_array retain];
    NSLog (@ "m_array1 [0] =% @, retain_m_array1_retainCount =% d", m_array1 [0], (int) m_array1.retainCount);
    
    // Assign the value of m_array to m_array2 through copy
    NSMutableArray * m_array2 = [m_array copy];
    NSLog (@ "m_array2 [0] =% @, copy_m_array2_retainCount =% d", m_array2 [0], (int) m_array2.retainCount);
    
    // Assign m_array to m_array3 through mytableCopy
    NSMutableArray * m_array3 = [m_array mutableCopy];
    NSLog (@ "m_array3 [0] =% @, mutable_m_array3_retainCount =% d", m_array3 [0], (int) m_array3.retainCount);
    
    // Print the address of each variable container object
    NSLog (@ "print out the address of each variable container object");
    NSLog (@ "m_array_p =% p", m_array);
    NSLog (@ "m_array_p1 =% p", m_array1);
    NSLog (@ "m_array_p2 =% p", m_array2);
    NSLog (@ "m_array_p3 =% p", m_array3);
    
    // Print the address of the element in each variable container
    NSLog (@ "print out the address of each element in the variable container");
    NSLog (@ "m_array_p [0] =% p", m_array [0]);
    NSLog (@ "m_array_p1 [0] =% p", m_array1 [0]);
    NSLog (@ "m_array_p2 [0] =% p", m_array2 [0]);
    NSLog (@ "m_array_p3 [0] =% p", m_array3 [0]);


The above code and the running results of the code are being tested to verify the following conclusions:



 1.retain: Always shallow copy. The reference count is added one at a time. Returns whether the object is mutable and consistent with the object being copied.



2.copy: The reference count does not change for a deep copy of a mutable object, and for an immutable object is a shallow copy, the reference count is added one at a time. Always returns an immutable object.



3.mutableCopy: Always deep copy, reference count does not change. Always returns a Mutable object.






Fine-print issues between custom class objects



In Objective-c, not all classes support copies, and only those that follow the Nscopying protocol support copy copies, and only those that follow the Nsmutablecopying protocol support mutablecopy copies. If the copy protocol is not followed, a copy error occurs.



If we want to support copy and Mutablecopy in our custom classes then we need to make the classes we define follow the nscopying and nsmutablecopying protocols, and the code is as follows:




Then rewrite-(ID) Copywithzone: (Nszone *) zone and-(ID) Mutablecopywithzone: (Nszone *) zone



Rewrite-(ID) Copywithzone: (Nszone *) Zone method as follows


// Shallow copy- (id) copyWithZone: (NSZone *) zone {return [self retain];} // Deep copy- (id) mutableCopyWithZone: (NSZone *) zone {Test * test = [[Test allocWithZone: zone] init]; test.property = self.property; return test;}






Deep and shallow copies in the 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.