NSArray:

//main.m

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

//这里为不可变数组赋值以可变字符串对象,稍后会作说明,此测试换成NSString也可。
        NSArray *array1 = [[NSArray alloc]initWithObjects:
                           [NSMutableString stringWithString:@"a"],
                           [NSMutableString stringWithString:@"b"],
                           [NSMutableString stringWithString:@"c"],
                           [NSMutableString stringWithString:@"d"], nil];
        

        NSArray *array2;
        NSArray *array3;
        NSArray *array4;
        
        
        array2 = array1;
        array3 = [array1 copy];
        array4 = [array1 mutableCopy];
        
        NSLog(@"array1 address = %p", array1); //输出array1指向的地址
        NSLog(@" ");
        NSLog(@"array2 address = %p", array2); //输出array2指向的地址
        NSLog(@" ");
        NSLog(@"array3 address = %p", array3); //输出array3指向的地址
        NSLog(@" ");
        NSLog(@"array4 address = %p", array4); //输出array4指向的地址
    }
    return 0;
}
 1 //运行结果:
 2 
 3 2016-06-05 18:07:55.919 copyTest2[2383:144656] array1 address = 0x1001025b0
 4 2016-06-05 18:07:55.920 copyTest2[2383:144656]  
 5 2016-06-05 18:07:55.920 copyTest2[2383:144656] array2 address = 0x1001025b0
 6 2016-06-05 18:07:55.920 copyTest2[2383:144656]  
 7 2016-06-05 18:07:55.920 copyTest2[2383:144656] array3 address = 0x1001025b0
 8 2016-06-05 18:07:55.920 copyTest2[2383:144656]  
 9 2016-06-05 18:07:55.920 copyTest2[2383:144656] array4 address = 0x100102d20
10 Program ended with exit code: 0

结果分析:

(1)array1,array2,array3都指向了相同的地址。array1的copy方法没有分配到新的内存地址,而MutableCopy方法却分配了新的内存。这与NSString的copy和MutableCopy方法得到的结果是一样的。详情参考我的另一篇文章:探讨NSString和NSMutableString的内存问题以及copy和MutableCopy两个方法

(2)理论上来说,array1在数组的层面上进行修改,会使得array2和array3跟着改变。

这里有很重要的附加说明:

①array1是不可变数组,所以我在前一句说在数组的层面上修改的时候,会说理论上,它实际上在数组的层面是不可以被修改的

②但这不意味着它不能被改变。我上面以可变字符串对其进行元素填充是有用意的,因为确实可以array1在数组元素的层面进行修改,而不是在数组的层面上修改具体做法是再定义一个可变字符串NSMutableString *mStr = array1[0],然后使用语句 [mStr appendString:@"AAAAA"]; 会导致array1[0]的值也会跟着变化。

 

他们之间的地址引用关系如图1所示:

图1

 

NSMutableArray:

 1 //main.m
 2 
 3 #import <Foundation/Foundation.h>
 4 
 5 int main(int argc, const char * argv[]) {
 6     @autoreleasepool {
 7         // insert code here...
 8         
 9         
10         NSMutableArray *array1 = [[NSMutableArray alloc]initWithObjects:
11                     [NSMutableString stringWithString:@"a"],
12                     [NSMutableString stringWithString:@"b"],
13                     [NSMutableString stringWithString:@"c"],
14                     [NSMutableString stringWithString:@"d"], nil];
15         
16         NSMutableArray *array2;
17         NSMutableArray *array3;
18         NSMutableArray *array4;
19 
20         NSMutableString *mStr = array1[0];  //定义一个可变字符串,用于在数组元素层面上修改数组元素
21         
22         NSLog(@"Before array1 changes:");
23         array2 = array1;
24         array3 = [array1 copy];
25         array4 = [array1 mutableCopy];
26         NSLog(@"array1 address is %p", array1); //array1指向的地址
27         NSLog(@"\narray1:%@", array1);          //array1原始内容
28         NSLog(@"array2 address is %p", array2); //array2指向的地址
29         NSLog(@"\narray2:%@", array2);          //array2原始内容
30         NSLog(@"array3 address is %p", array3); //array3指向的地址
31         NSLog(@"\narray3:%@", array3);          //array3原始内容
32         NSLog(@"array4 address is %p", array4); //array4指向的地址
33         NSLog(@"\narray4:%@", array4);          //array4原始内容
34         
35         [array1 insertObject:@10000 atIndex:2];     //array1在数组的层面上修改
36         NSLog(@" ");
37         NSLog(@"After the first changes of array1:");
38         NSLog(@"array1 address is %p", array1);    //第一次修改后array1指向的地址
39         NSLog(@"\narray1:%@", array1);             //第一次修改后array1的数据
40         NSLog(@"array2 address is %p", array2);     //第一次修改后array2指向的地址
41         NSLog(@"\narray2:%@", array2);              //第一次修改后array2的数据
42         NSLog(@"array3 address is %p", array3);     //第一次修改后array3指向的地址
43         NSLog(@"\narray3:%@", array3);              //第一次修改后array3的数据
44         NSLog(@"array4 address is %p", array4);     //第一次修改后array4指向的地址
45         NSLog(@"\narray4:%@", array4);              //第一次修改后array4的数据
46 
47         
48         [mStr appendString:@"AAAAAAAAAAAA"];        //在数组元素的层面上修改
49         NSLog(@" ");
50         NSLog(@"After the second changes of array1:");
51         NSLog(@"array1 address is %p", array1);     //第二次修改后array1指向的地址
52         NSLog(@"\narray1:%@", array1);              //第二次修改后array1的数据
53         NSLog(@"array2 address is %p", array2);     //第二次修改后array2指向的地址
54         NSLog(@"\narray2:%@", array2);              //第二次修改后array2的数据
55         NSLog(@"array3 address is %p", array3);     //第二次修改后array3指向的地址
56         NSLog(@"\narray3:%@", array3);              //第二次修改后array3的数据
57         NSLog(@"array3 address is %p", array3);     //第二次修改后array3指向的地址
58         NSLog(@"\narray3:%@", array3);              //第二次修改后array3的数据
59         NSLog(@"array4 address is %p", array4);     //第二次修改后array4指向的地址
60         NSLog(@"\narray4:%@", array4);              //第二次修改后array4的数据
61     }
62     return 0;
63 }
  1 //运行结果
  2 
  3 2016-06-25 14:57:46.511 copyTest2[512:8667] Before array1 changes:
  4 2016-06-25 14:57:46.512 copyTest2[512:8667] array1 address is 0x100108160
  5 2016-06-25 14:57:46.512 copyTest2[512:8667] 
  6 array1:(
  7     a,
  8     b,
  9     c,
 10     d
 11 )
 12 2016-06-25 14:57:46.512 copyTest2[512:8667] array2 address is 0x100108160
 13 2016-06-25 14:57:46.512 copyTest2[512:8667] 
 14 array2:(
 15     a,
 16     b,
 17     c,
 18     d
 19 )
 20 2016-06-25 14:57:46.512 copyTest2[512:8667] array3 address is 0x103101050
 21 2016-06-25 14:57:46.512 copyTest2[512:8667] 
 22 array3:(
 23     a,
 24     b,
 25     c,
 26     d
 27 )
 28 2016-06-25 14:57:46.512 copyTest2[512:8667] array4 address is 0x103101080
 29 2016-06-25 14:57:46.512 copyTest2[512:8667] 
 30 array4:(
 31     a,
 32     b,
 33     c,
 34     d
 35 )
 36 2016-06-25 14:57:46.512 copyTest2[512:8667]  
 37 2016-06-25 14:57:46.512 copyTest2[512:8667] After the first changes of array1:
 38 2016-06-25 14:57:46.512 copyTest2[512:8667] array1 address is 0x100108160
 39 2016-06-25 14:57:46.512 copyTest2[512:8667] 
 40 array1:(
 41     a,
 42     b,
 43     10000,
 44     c,
 45     d
 46 )
 47 2016-06-25 14:57:46.512 copyTest2[512:8667] array2 address is 0x100108160
 48 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 49 array2:(
 50     a,
 51     b,
 52     10000,
 53     c,
 54     d
 55 )
 56 2016-06-25 14:57:46.513 copyTest2[512:8667] array3 address is 0x103101050
 57 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 58 array3:(
 59     a,
 60     b,
 61     c,
 62     d
 63 )
 64 2016-06-25 14:57:46.513 copyTest2[512:8667] array4 address is 0x103101080
 65 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 66 array4:(
 67     a,
 68     b,
 69     c,
 70     d
 71 )
 72 2016-06-25 14:57:46.513 copyTest2[512:8667]  
 73 2016-06-25 14:57:46.513 copyTest2[512:8667] After the second changes of array1:
 74 2016-06-25 14:57:46.513 copyTest2[512:8667] array1 address is 0x100108160
 75 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 76 array1:(
 77     aAAAAAAAAAAAA,
 78     b,
 79     10000,
 80     c,
 81     d
 82 )
 83 2016-06-25 14:57:46.513 copyTest2[512:8667] array2 address is 0x100108160
 84 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 85 array2:(
 86     aAAAAAAAAAAAA,
 87     b,
 88     10000,
 89     c,
 90     d
 91 )
 92 2016-06-25 14:57:46.513 copyTest2[512:8667] array3 address is 0x103101050
 93 2016-06-25 14:57:46.513 copyTest2[512:8667] 
 94 array3:(
 95     aAAAAAAAAAAAA,
 96     b,
 97     c,
 98     d
 99 )
100 2016-06-25 14:57:46.513 copyTest2[512:8667] array3 address is 0x103101050
101 2016-06-25 14:57:46.513 copyTest2[512:8667] 
102 array3:(
103     aAAAAAAAAAAAA,
104     b,
105     c,
106     d
107 )
108 2016-06-25 14:57:46.514 copyTest2[512:8667] array4 address is 0x103101080
109 2016-06-25 14:57:46.514 copyTest2[512:8667] 
110 array4:(
111     aAAAAAAAAAAAA,
112     b,
113     c,
114     d
115 )
116 Program ended with exit code: 0

这次先上图:

图2(改变前)

 

 

图3(第一次改变后)

 

 

图4(第二次改变后)

 

结果分析:

(1)根据图2、图3和图4,结论是显而易见的。NSMutableArray响应Copy方法不同于NSArray的Copy方法,前者响应Copy方法会再分配新的内存给Copy的新副本,后者却不会(因此,可以说Copy对NSArray来说执行的是浅复制,对NSMutableArray来说执行的是深复制,关于深浅复制的理解,可以看这个链接下的回答 https://baike.1688.com/doc/view-d36106768.html,但是NSMutableArray响应Copy或者MutableCopy方法执行的这种深复制也并“不彻底”,在我们下面会讨论到的归档,将会看到一种更为彻底的深复制);相同的是两者的MutableCopy都能分配新的内存给新副本。所以两个可变数组array3、array4都指向了新的地址,与array1不同,因此对array1响应的 insertObject:atIndex: 方法array3和array4都不会受到影响。

(2)同时,我们在这一次实验结果中可以看到在数组元素层面上修改数组元素。

 

 使用归档程序复制MutableArray对象:

 1 //main.m
 2 
 3 #import <Foundation/Foundation.h>
 4 
 5 int main(int argc, const char * argv[]) {
 6     @autoreleasepool {
 7         NSData *data;
 8         NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],[NSMutableString stringWithString:@"two"],[NSMutableString stringWithString:@"three"], nil];
 9         
10         NSMutableArray *dataArray2 ;
11         NSMutableString *mStr;
12         
13         //使用归档器进行深复制
14         data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
15         
16         dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
17         
18         mStr = dataArray2[0];
19         [mStr appendString:@"ONE"];
20         
21     
22         NSLog(@"dataArray:");
23         for(NSString *elem in dataArray)
24         {
25             NSLog(@"%@", elem);
26         }
27         NSLog(@"\ndataArray2:");
28         for(NSString *elem in dataArray2)
29         {
30             NSLog(@"%@", elem);
31         }
32         
33         //查看dataArray和dataArray2两个可变数组的地址
34         NSLog(@"\n");
35         NSLog(@"%p", dataArray);
36         NSLog(@"%p", dataArray2);
37         
38         //查看dataArray和dataArray2两个可变数组首个元素的地址
39         NSLog(@"\n");
40         NSLog(@"%p", dataArray[0]);
41         NSLog(@"%p", dataArray2[0]);
42     }
43     return 0;
44 }
45     
 1 //运行结果:
 2 
 3 
 4 2016-07-02 12:54:13.426 Objective-C-p450[1122:29001] dataArray:
 5 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] one
 6 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] two
 7 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] three
 8 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] 
 9 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] dataArray2:
10 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] oneONE
11 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] two
12 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] three
13 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] 
14 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] 0x1007005e0
15 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] 0x100703850
16 2016-07-02 12:54:13.427 Objective-C-p450[1122:29001] 
17 2016-07-02 12:54:13.428 Objective-C-p450[1122:29001] 0x100700250
18 2016-07-02 12:54:13.428 Objective-C-p450[1122:29001] 0x100702720
19 Program ended with exit code: 0

 

图5(使用归档执行深复制)

 

结果分析:

(1)通过图5与图4的对比可以发现,图5不但给数组分配了空间,同时给数组元素的引用对象也分配了空间,即在原来只有@
"one",@"two",@"three" 3个字符串的情况下,又新分配了三个空间存储新的3个字符串@"one",@"two",@"three"。图4中MutableArray响应的无论是Copy方法还是MutableCopy方法都仅仅是给数组分配了新空间,而它们数组元素引用的都是堆中唯一一份字符串@""

(2)dataArray和dataArray2的数组元素不再是引用同一个对象了,因此使用mStr试图去改变dataArray2[0],并不影响dataArray[0]。我们在最后输出了dataArray和dataArray2,以及dataArray[0]和dataArray2[0],更清晰地看到它们的地址完全不同。

posted on 2016-06-05 18:34  SharpeyeKardel  阅读(671)  评论(0编辑  收藏  举报