0

我正在尝试用字典测试复制。如果我正确理解了我的书,当我们复制原始字典时,新字典中的对象将仅引用原始字典中的那些元素(类似于数组的浅拷贝)。在下面的示例中,我将一个字符串对象添加到字典中,然后复制字典并打印两个字典的结果。然后我更改字符串的值并再次打印两个字典。但是,结果与字符串的原始值相同。字典的最后一次打印不应该显示字符串的新值吗?

NSMutableString * phoneRef = [NSMutableString stringWithString:@"444"];
NSString * phoneKey = @"phone";
NSDictionary * myDict = [NSDictionary dictionaryWithObjectsAndKeys: phoneRef, phoneKey, nil];

NSMutableDictionary *dictCopy = [myDict mutableCopy];

NSLog(@"%@", myDict);
NSLog(@"%@", dictCopy);

phoneRef = [NSMutableString stringWithString:@"555"];

NSLog(@"%@", myDict);
NSLog(@"%@", dictCopy);
4

1 回答 1

2

我在评论中猜测答案,因为我目前无法使用 Mac,但这就是正在发生的事情。

当您将对象添加到字典时,字典会保留指向这些对象的指针。

当你这样做时:

phoneRef = [NSMutableString stringWithString:@"555"];
//or even just phoneRef = @"555";

您不会更改phoneRef最初指向的内存位置的内容(字典指向的内存位置)。您正在更改phoneRef指针的值,将其指向内存中包含字符串 value 的新位置@"555"

然而,字典仍然指向旧的内存位置,它仍然包含@"444".

但是,使用这种方法:

[phoneRef setString:@"555"];

或者您直接在实例化对象上调用的任何其他方法phoneRef(例如replaceOccurrencesOfString:withString:options:range:、 或replaceCharactersInRange:withString:等),您实际上是在修改phoneRef实际指向的内存地址的内容。字典在技术上是 100% 完全未经修改的。它们只包含指向内存地址的指针(我不认为它们甚至不知道它们指向哪种对象)。使用该setString:方法,您可以更改字典指向的内存地址的值。


为了更清楚地了解正在发生的事情,您可以使用以下内容打印指针的值(所有内容指向的内存地址):

NSLog(@"Address of phoneRef: %p", &phoneRef);

在之前和之后phoneRef = [NSMutableString stringWithString:@"555"];以及之前和之后加上这条线,[phoneRef setString:@"555"];以更清楚地看到发生了什么。

于 2013-11-08T02:06:00.520 回答