IOS talks deep shallow copy


Shallow copy

Shallow copy is the copy of the memory address, so that the target object pointer and the source object point to the same memory space, when the memory is destroyed At that time, several pointers to this piece of memory need to be redefined before they can be used, or they will become wild pointers.

Share a picture

Shallow copy means copy pointing to the original object The pointer to make the reference count of the original object +1, which can be understood as creating a new pointer to the original object, but not creating a brand new object.

deep copy

Deep copy refers to the specific content of the copy object, and the memory address is allocated independently. After the copy is over, although the two objects are stored The value is the same, but the memory address is different, and the two objects do not affect each other or interfere with each other.

Share a picture

Deep copy means copy out and original Only a new object with the same value but a completely different memory address has nothing to do with the original object after creation.

Summary

Deep copy is content copy, shallow copy is pointer copy. The essential difference lies in:

  • Whether to open a new memory address
  • Whether it affects the reference count of the memory address

Case analysis

In iOS, deep copy and shallow copy are more complicated, involving copy and mutableCopy of container and non-container, mutable and immutable objects. The following examples are used to analyze one by one:

copy and mutableCopy of non-collection objects

immutable object NSString

1
< span class="line">2
3
4
5
6
7
8
9
10
11
12
13
14
15
 -(void) noMutableNSStringTest
{
NSString *str1 = @"test001";< br>
NSMutableString *str2 = [str1 copy];
/ /copy What is returned is an immutable object, str2 cannot be modified, so a crash will occur
//[str2 appendString:@"test"];

NSMutableString *str3 = [str1 mutableCopy];
[str3 appendString :@"modify"];

NSLog(@"str1:%p-%@ rn" ,str1,str1);
NSLog(@"str2:%p-%@ rn",str2,str2);
NSLog(@"str3:%p-%@ rn",str3,str3);
}

Print result:

< td class="gutter">
1
2
3
2017-07-20 18:02:10.642 beck.wang[1306 :169414] str1:0x106abdbd0-test001 
2017-07-20 18:02:10.643 beck.wang[1306:16 9414] str2:0x106abdbd0-test001
2017-07-20 18:02:10.643 beck.wang[1306:169414] str3:0x608000260940-test001modify< br>

Analysis: The address of str1 and str2 is the same and different from the address of str3. The copy of NSString is a shallow copy, and The object returned by copy is an immutable object; mutableCopy is a deep copy.

Variable object NSMutableString

< pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void) mutableNSStringTest
{
NSMutableString *mstr1 = [NSMutableString stringWithString:@"test002"];

NSMutableString *mstr2 = [mstr1 copy];
//copy returns an immutable object, mstr2 Cannot be modified, so it will crash
//[str2 appendString:@"test"];

NSMutableString *mstr3 = [mstr1 mutableCopy];
[mstr3 appendString:@"modify"];< /span>

NSLog(@"mstr1:%p-%@ rn",mstr1,mstr1); span>
NSLog(@"mstr2:%p-%@ rn",mstr2,mstr2);
NSLog(@ "mstr3:%p-%@ rn",mstr3,mstr3);
}

Print results:

< pre>1
2
3
2017-07-20 18:14:35.789 beck.wang[1433:180881] mstr1:0x610000075e40-test002 
2017-07-20 18:14:35.790 beck.wang[1433: 180881] mstr2:0xa323030747365747-test002
2017-07-20 18:14:35.790 beck.wang[1433:180881] mstr3:0x610000074480-test002modify< br>

Analysis: The addresses of mstr1, mstr2, and mstr3 are all different. Both NSMutableString object copy and mutableCopy are deep copies. And the object returned by copy is an immutable object.

copy and mutableCopy of collection objects

immutable object NSArray

1
2
3
4
5
6
7
8
9
10
11
- (void) mutableNSArrayTest
{< /span>
NSArray *arry1 = [[NSArray alloc] initWithObjects:@"value1", @"value2",nil];

NSArray *arry2 = [arry1 copy];
NSArray *arry3 = [arry1 mutableCopy] ;

NSLo g(@"arry1:%p-%@ rn",arry1,arry1);
NSLog(@"arry2:%p-%@ rn",arry2, arry2);
NSLog(@"arry3:%p-%@ rn",arry3,arry3);
}

Print results:

1
2
3
4
5
6
7
8
9
10
11
< span class="line">12

2017-07-20 18:33 :53.707 beck.wang[1502:194476] arry1:0x60800003b480-(
value1,
value2
span>
) < br>2017-07-20 18:33:53.708 beck.wang[1502:194476] arry2:0x60800003b480-(
value1,
value2
)
2017-07 -20 18:33:53.708 beck.wang[1502:194476] arry3:0x60800004cd20-(
value1,
value2
)

Analysis: The addresses of arry1 and arry2 are the same, but the addresses of arr3 are different. The copy of NSArray is a shallow copy, and the object returned by copy is an immutable object; mutableCopy is a deep copy.

Variable Object NSMutableArray

< /tbody>

< pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void) NSMutableArrayTest
{
NSMutableArray *marry1 = [[NSMutableArray alloc] initWithObjects:@"value1", @"value2",nil];

NSMutableArray *marry2 = [marry1 copy];

//copy returns an immutable object, marry2 cannot be modified, so it will crash
//[marry2 addObject:@"value3"];

NSMutableArray *marry3 = [marry1 mutableCopy];

NSLog(@"marry1:%p-%@ rn",marry1,marry1);
NSLog(@"marry2:%p-%@ rn",marry2,marry2);
NSLog(@"marry3 :%p-%@ rn",marry3,marry3);
}

Print results:

 1
2
3
4
5
6
7
8
9
10
11
12
2017-07-20 18:55:43.243 beck.wang[1577:204641] marry1:0x600000048d60-(
value1,
value2
)
2017-07-20 18:55:43.244 beck.wang[1577:204641] marry2:0x600000026000-(
value1,
value2
)
2017-07-20 18:55:43.244 beck.wang[1577:204641] marry3:0x6000000494b0-(
value1,
value2
)

Analysis: marry1, The addresses of marry2 and marr3 are different. Both NSMutableArray object copy and mutableCopy are deep copies, and the objects returned by copy are immutable objects.

Special attention is paid: For collection-like mutable objects, deep copy is not strictly a deep copy, it can only be regarded as a single-layer deep copy< /strong>, that is, although the memory address is newly opened, but the value stored in the memory (that is, the element in the array is still the previous array element value, and there is no other copy), this is called single-level deep copy.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< span class="line">17
18
19
20
21
22
23
24
25
26
27
28
29
30
< span class="line">-(void)singleNSMutableArrayTest
{
NSMutableArray *marry1 = [[NSMutableArray alloc] init];

NSMutableString *mstr1 = [[NSMutableString alloc]initWithString:@"value1" ];
NSMutableString *mstr2 = [[NSMutableString alloc]initWithString:@"value2"];
< /span>
[marry1 addObject:mstr1];
[marry1 addObject:mstr2];

NSMutableArray *marry2 = [marry1 copy];
NSMutableArray *marry3 = [marry1 mutableCopy];

NSLog(@"marry1: %p-%@ rn",marry1,marry1);
NSLog(@"marry2:%p-%@ rn",marry2,marry2);
NSLog(@"marry3:%p-% @ rn",marry3,marry3);
NSLog(@"Array element address: value1:%p-value2:%p rn",marry1[0],marry1 [1]);
NSLog(@"Array element address: value1:%p-value2:%p rn",marry2[0],marry2[1]) ;
NSLog(@"Array element address: value1:%p-value2:%p rn",marry3[0],marry3[1]);

NSLog(@"rn------------------ After modifying the original value------------------------rn");
[mstr1 appendFormat :@"aaa"];

NSLog(@"marry1:%p-%@ rn" ,marry1,marry1);
NSLog(@"marry2:%p-%@ rn",marry2,marry2);
NSLog(@"marry3:%p-%@ rn",marry3,marry3);
NSLog(@" array element address: value1:% p-value2:%p rn",marry1[0],marry1[1]);
NSLog(@"array element address: value1:%p-value2:%p rn",marry2[0],marry2[1]);
NSLog (@"Array element address: value1:%p-value2:%p rn",marry3[0],marry3[1]);
}

Print results:

< tbody>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15< /span>
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33< /span>
 
2017- 07-20 19:48:24.539 beck.wang[1750:230132] marry1:0x60800004ae00-(
value1,
value2
)
2017-07-20 19:48:24.539 beck.wang[1750 :230132] marry2:0x608000023f00-(
value1,
value2
)
2017-07-20 19:48:24.539 beck.wang[1750:230132] marry3:0x60800004abc0-(< /span>
value1,
value2
)
2017-07-20 19:48:24.540 beck.wang[1750:230132] Array element address: value1:0x60800006df40-value2:0x60800006cb40
< span class="line">2017-07-20 19:48:24.540 beck.wang[1750:230132] Array element address: value1:0x60800006df40-value2:0x60800006cb40

2017-07-20 19:48:24.540 beck.wang[1750:230132] Array element address: value1:0x60800006df40-value2:0x60800006cb40
2017-07-20 19:48:24.540 beck.wang[1750:230132]
------------------After modifying the original value ------------------------
2017-07-20 19:48:24.540 beck .wang[1750:230132] marry1:0x60800004ae00-(
value1aaa,
value2< br>)
2017-07-20 19:48:24.540 beck.wang[1750:230132] marry2:0x608000023f00-(< /span>
value1aaa,
value2
)
2017-07-20 19:48:24.540 beck.wang[1750:230132] marry3:0x60800004abc0-(
value1aaa,
< span class="line"> value2

)
2017-07-20 19:48:24.541 beck .wang[1750:230132] Array element address: value1:0x60800006df40-value2:0x60800006cb40
2017-07-20 19:48:24.541 beck.wang[1750:230132 ] Array element address: value1:0x60800006df40-value2:0x60800006cb40
2017-07-20 19:48:24.541 beck.wang[1750:230132] Array element address: value1 :0x60800006df40-value2:0x60800006cb40

Analysis: Before modifying the original value, marry1, The addresses of marry2 and marr3 are not the same. Obviously copy and mutableCopy are both deep copies, but from the printed results after modifying the original value, the deep copy here is only a single-layer deep copy: the memory address is newly opened, but the value in the array The value still points to the original array, so that after the original value is modified, the values ​​in marry2 and marr3 are all modified. In addition, it is obvious from the printed array element addresses that the array element addresses of marry1, marry, and marr3 are exactly the same before and after the modification, which further proves this point.

Expanded thinking: complete deep copy of collection object

For collection objects, deep copy is only a single deep copy , Is there a way to achieve deep copy of each layer? The answer is yes, currently we can do this:

Archive and Unzip Dafa

< tr>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void) deplyFullCopy
{< /span>
NSMutableArray *marry1 = [[NSMutableArray alloc] init];

NSMutableString *mstr1 = [[N SMutableString alloc]initWithString:@"value1"];
NSMutableString *mstr2 = [[NSMutableString alloc]initWithString:@"value2"];

[marry1 addObject:mstr1];
[marry1 addObject:mstr2 ];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:marry1];
NSArray *marray2 = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:nil];

NSLog(@"marry1:%p-%@ rn",marry1,marry1);
NSLog(@"marry2:%p-%@ rn", marray2,marray2);
NSLog(@"Array element address: value1:%p-value2:%p rn",marry1[0],marry1[1]) ;
NSLog(@"Array element address: value1:%p-value2:%p rn",marray2[0],marray2[1]);
}

Print results:

1
2
3
4
5
6
7
8
9
< span class="line">10
2017-07-20 20:04 :38.726 beck.wang[1833:242158] marry1:0x600000048a00-(
value1,
value2
span>
)
2017-07-20 20:04:38.726 beck.wang[1833:242158] marry2:0x600000049780 -(
value1,
value2
)
2017-07-20 20:04:38.726 beck.wang[1833:242158] Array element address: value1:0 x600000066300-value2:0x600000067000
2017-07-20 20:04:38.726 beck.wang[1833:242158] Array element address: value1:0x600000066740-value2:0x600000066f40< /span>

-(instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag;

1
2
3< /span>
4
5
6
7
8
9< br>10
11
12
13
14
15
16
17

- (void) deplyFullCopy2
{
NSMutableArray *marry1 = [[NSMutableArray alloc] init];

NSMutableString *mstr1 = [[NSMutableString alloc]initWithString:@"value1"];
NSMutableString *mstr2 = [[NSMutableString alloc]initWithString:@"value2"];

[ marry1 addObject:mstr1];
[marry1 addObject:mstr2];

NSArray *marray2 = [[NSArray alloc] initWithArray:marry1 copyItems:YES];

NSLog(@"marry1:%p-%@ rn",marry1,marry1);
NSLog(@"marry2:%p-%@ rn",marray2,marray2);
NSLog( @"Array element address: value1:%p-value2:%p rn",marry1[0],marry1[1]);
NSLog(@"array element Address: value1:%p-value2:%p rn",marray2[0],marray2[1]);
}

Print result:

1
2
3
4
5
6
7
8
9
10
2017- 07-20 20:08:04.201 beck.wang[1868:246161] marry1:0x610000050320-(
value1,
value2
)
2017-07-20 20:08:04.202 beck.wang[1868 :246161] marry2:0x6100002214c0 -(
value1,
value2
)
2017-07-20 20:08:04.202 beck.wang[1868:246161] Array element address: value1:0x610000265600-value2:0x610000266400 < br>2017-07-20 20:08:04.202 beck.wang[1868:246161] Array element address: value1:0xa003165756c61766-value2:0xa003265756c61766

Guidelines

  • No1: Both copy and mutableCopy methods of mutable objects It is a deep copy (the distinction is between a complete deep copy and a single-layer deep copy).
  • No2: The copy method of immutable objects is a shallow copy, and the mutableCopy method is a deep copy.
  • No3: The objects returned by the copy method are immutable objects.

Share a picture

Other Statements

In the ios development process, there are two concepts of object and container. Object copy is shallow copy, and mutable copy is deep copy. The container also refers to the above method, but you need to remember that the copy of the container containing the object, whether you use copy or mutablecopy, will be a shallow copy. If you want to achieve deep copy of an object, you must provide a copy method yourself. For the method provided by yourself, see the following points of attention.

As mentioned above, the copy of the container is only a single deep copy.

Practical thinking and application

Case

@property (nonatomic,copy) NSString * in B str; is to prevent the A controller, when calling the Str of the B controller, pass in a variable string

If the input is a variable string, use the Copy attribute to make a deep copy change Immutable

If the incoming string is immutable, using the Copy attribute will make a shallow copy, that is, the copy pointer points to the content

If you use Strong, if If the variable character string of controller A changes, the character string in controller B will be affected and change accordingly

Think

【? ? ? ? ? Therefore, in the iOS properties, Strong and retain types will make the reference count +1, and when copying immutable objects, the reference count will be +1 and the content will not change, so it can be visually understood as a shallow copy].

Don’t confuse the reference count with the deep copy, because the deep copy, in any case, the reference count will be +1, you can’t say that the attribute declares Strong, it means that a shallow copy or a deep copy is performed, because Strong If this is the case, there is no operation of copying the pointer or copying the content at all.

Leave a Comment

Your email address will not be published.