IOS - In-depth understanding of deep copy and shallow copy

Deep copy and shallow copy in OC array

Shallow copy: that is, a pointer copy, the source object and the new object point to the same address, that is to say, a new file needs to be recovered from the shallow copy, but the addresses of the two files are still the same. Shallow copy means that only immutable arrays (such as: NSArray, NSSet, NS dictionary) encounter copy, which is a shallow copy, and the rest are deep copies.

Dog * dog1 = [Dog new];
// Here is a shallow copy, that is, a pointer copy
Dog * dog2 = dog1;

For deep copying, the classes defined by yourself generally need to follow the NSCopying, NSMutableCopying protocols

Dog.h

@interface Dog : NSObject<NSCopying, NSMutableCopying>
@property (nonatomic) NSInteger age;
@end
Dog.m

@implementation Dog
- (id)copyWithZone:(NSZone *)zone
{
    Dog * dog = [[self class] allocWithZone:zone];
    dog.age = self.age;
    return dog;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    Dog * dog = [[self class] allocWithZone:zone];
    dog.age = self.age;
    return dog;
}

- (NSString *) description {
    return [NSString stringWithFormat:@"dog age: %ld", self.age];
}

@end
main.m

Dog * dog1 = [Dog new];
dog1.age = 5;

NSLog(@"dog1: %p, %@", dog1, dog1);

// mutableCopy returns a mutable object, which can naturally set the attribute value of the object
Dog * dog2 = [dog1 mutableCopy];
dog2.age = 10;

// The object returned by copy can also set the property value of the object
// So, from this point of view, in fact, the copy and mutableCopy functions of the custom implementation are consistent, and both return mutable objects
Dog * dog2 = [dog1 copy];
dog2.age = 10;

NSLog(@"dog2: %p, %@", dog2, dog2);


Deep copy and shallow copy in OC mutable array

"The array only stores the address of the object, not the body of the object."

So, after making a deep copy of the array, the addresses of the objects in it are indeed recreated.

NSMutableArray * arr1 = [NSMutableArray new];

for (int i = 0; i < 3; i++) {
    Dog * dog = [Dog new];
    [arr1 addObject:dog];
}

NSLog(@"arr1: %p, %@", arr1, arr1);
NSMutableArray * arr2 = [arr1 mutableCopy];
NSLog(@"arr2: %p, %@", arr2, arr2);
operation result:
2017-010-10 10:55:39.895 deep copy vs shallow copy [901:303] arr1: 0x1001089c0, (
    "<Dog: 0x100108430>",
    "<Dog: 0x100109fc0>",
    "<Dog: 0x100109fd0>"
)
2017-10-10 10:55:39.917 deep copy vs shallow copy [901:303] arr2: 0x100301ad0, (
    "<Dog: 0x100108430>",
    "<Dog: 0x100109fc0>",
    "<Dog: 0x100109fd0>"
)

Because "the array only stores the address of the object, not the body of the object." Therefore, the space of the Dog object is not copied.

So a "deep copy" of a mutable array doesn't copy all of its elements, the object elements in it are only shallowly copied!

Solution: Re-copy all objects

NSMutableArray * arr2 = [NSMutableArray new];
for (int i = 0; i < arr1.count; i++) {
    Dog * newDog = [arr1[i] copy];
    [arr2 addObject:newDog];
}

NSLog(@"arr2: %p, %@", arr2, arr2);

For the deep copy of the array in OC, it cannot be taken for granted that the element space in it has been copied. In fact, the elements in it are just shallow copies!

If you need to implement a deep copy, you can perform a deep copy one by one and add it back to the mutable array!


COPY returns a copy of an immutable object, and MutalbeCopy returns a copy of a mutable object.

NSArray *array=[NSArray arrayWithObjects:@"one",@"two", nil];
NSMutableArray *array1=[array copy];
[array1 addObject:@"three"];  //error
NSMutableArray *array2=[array mutableCopy];
[array2 addObject:@"three"];  //right
// insert code here...
NSLog(@"Hello, World!");


Compare and Difference

The basic concept of copying objects: copy an object as a copy, and open up a new memory to store the copy object.

If an object wants to have the function of copying, it must implement the protocol and the protocol

The commonly used objects that come with NSObject are: NSNumber, NSString, NSArray, NSDictionary, NSMutableArray, NSMutableDictionay, NSMutableString. The objects generated by copy are immutable, and the objects generated by mutableCopy are variable.

Difference between COPY and MutableCopy

COPY returns a copy of an immutable object, and MutalbeCopy returns a copy of a mutable object.


Shallow copy and deep copy

Shallow copy completely copies the object itself, and the attributes and contained objects in the object are not copied.

Shallow copy just copies the pointer and does not create a new memory space.

deep copy copies everything, including properties of objects and other objects

The Foundation framework supports copied classes, the default is shallow copy


custom copy of object

The object has the copy feature and must implement the NSCopying and NSMutableCopying protocols, and implement the copyWithZone and mutableCopyWithZone methods of the protocol.

The difference between deep copy and shallow copy lies in the implementation of copyWithZone method,


The relationship between copy, mutableCopy and retain

In the Foundation object, when copy is an immutable object, the effect is equivalent to retain

When using mutableCopy, regardless of whether the source object is mutable or not, the copy is mutable and implements a true copy

When we copy a mutable object, the copy object is immutable.


NSFoundation, when we copy an immutable object, the default copy is a shallow copy, which is equivalent to retain

When using mutableCopy, a deep copy is implemented regardless of whether the object is mutable or not

retain is equivalent to two objects pointing to the same pointer


Summary: copy and mutableCopy:
copy: deep copy for mutable objects and shallow copy for immutable objects. Returns whether the object is mutable and consistent with the copied object.
mutableCopy: Always a deep copy. Always returns a mutable object.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325569271&siteId=291194637