我确实找到了关于这个主题的一些讨论,但这超出了我目前的理解水平。我正在阅读Kochan的“Objective-C,4e编程”,并在关于NSString对象的部分。首先,我正在玩的代码,所以我可以问我的问题:
NSString *strA = @"StringA";
NSString *strB = @"StringB";
NSLog(@"Value of strA: %@",strA);
NSLog(@"Value of strB: %@",strB);
strB = strA; // strB should point to strA's memory location
NSLog(@"New value of strB: %@",strB); //correctly logs as "StringA"
strA = @"StringA has been changed.";
NSLog(@"New value of strB: %@",strB); //logs as "StringA" still
NSLog(@"New value of strA: %@",strA); //correctly logs as "StringA has been changed"
我的理解是说strB = strA意味着strB指向strA的内存位置,因此对strA的任何更改也会转到strB。但是,这不会发生。 Kochan说它应该是,并且绕过它建议使用
strB = [NSString stringWithString: strA];
从我所看到的,两种方法都有效。我可以说strB = strA,然后更改strA,但是strB仍然保留它收到的值(strA的值只是在更改之前)。
我认为这可能来自NSString是不可变的,但如果是这种情况,为什么我实际上可以在初始化后更改str1和str2的值?我在这里错过了什么?感谢。
答案 0 :(得分:3)
好像你已经没有足够的答案......
我认为一个或三个图表将帮助您了解代码示例中发生的情况。
首先,您的代码执行此操作:
NSString *strA = @"StringA";
NSString *strB = @"StringB";
这使你的应用程序的内存看起来像这样:
左侧是您的本地变量strA
和strB
。它们只是指向内存中对象的指针。
中间是字符串对象。这些是由编译器在您的应用程序中预先创建的,因为它们出现在您的源代码中。
右边是字符串对象的实际字符。这些也是由编译器在您的应用程序中预先创建的。
接下来,您的代码执行此操作:
strB = strA;
现在您的应用内存如下所示:
请注意,您的本地变量strB
已更改,但对象和字符未更改。
最后,您的代码执行此操作:
strA = @"StringA has been changed.";
这使你的应用程序的内存看起来像这样:
您的本地变量strA
已更改,但对象和字符仍未更改。
答案 1 :(得分:1)
我的理解是说strB = strA意味着strB是 指向strA的内存位置,因此对strA的任何更改也会 转到strB。
是的,虽然可以更明确地说strB
和strA
都指向同一个对象。
我可以说strB = strA,然后改变strA,但是strB仍然保留了 它收到的值(在更改之前strA的值)。
如果您更改strA
,那么您必须使strA
指向其他字符串。 NSStrings是不可变的,因此无法更改它们 - 您只能替换它们。所以,如果你说的话:
strA = [strA stringByAppendingString:@"foo"];
然后strA
不再指向原始字符串。当然,strB
仍然指向原始对象,并且该对象保持不变,因此strA
指向的字符串和strB
指向的字符串是不同的对象。
我在这里缺少什么?
我认为您正在考虑在执行赋值strB = strA;
时创建新对象,但实际上两个指针都将在该语句之后指向同一个对象。当你“改变”strA
时,就会创建一个新对象。
现在,如果你在讨论 mutable 字符串,那么事情会有所不同,你当然可以改变它们。然后你会遇到这样的情况:
NSMutableString *mstrA = [@"foo" mutableCopy];
NSMutableString *mstrB = mstrA; // now mstrB points to the same object as mstrA
[mstrA appendString:@"bar"];
NSLog(@"%@", mstrB); // will log @"foobar" because the string actually changed
答案 2 :(得分:0)
我的理解是说strB = strA意味着strB指向strA的内存位置,因此对strA的任何更改也会转到strB。
改变strA的内存位置 - 是的。更改为指向同一位置的完全不相关的指针,现在指向其他位置 - 否。
答案 3 :(得分:0)
有两种方法可以考虑这里发生的事情。一个稍微低一点的是,你正在处理一个名为 pointer 的构造。指针保存内存地址,与int
变量保存整数值的方式完全相同。如果您将int
分配给另一个int
,则更改第一个,第二个不会更改:
int i1 = 10;
int i2 = i1;
i1 = 600; // i2 still 10
指针也是如此。
另一种(可能更有效)的方式是strA
和strB
实际上是对象的名称。如果通过一个名称将对象分配给另一个名称,则两个名称都包含相同的对象。除了内存管理和对象生存期之外,您可以将一个名称重新分配给另一个对象,另一个名称将继续指向原始对象。