0

我确实找到了一些关于这个话题的讨论,但这超出了我目前的理解水平。我正在阅读 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 的值?我在这里想念什么?谢谢。

4

4 回答 4

3

好像你已经没有足够的答案了......

我认为一到三个图表将帮助您了解代码示例中发生的事情。

首先,您的代码执行此操作:

NSString *strA = @"StringA";
NSString *strB = @"StringB";

这使您的应用程序的内存看起来像这样:

内存图1

左边是你的局部变量,strAstrB. 它们只是指向内存中对象的指针。

中间是字符串对象。这些是由编译器在您的应用程序中预先创建的,因为它们出现在您的源代码中。

右边是字符串对象的实际字符。这些也是编译器在您的应用程序中预先创建的。

接下来,您的代码执行此操作:

strB = strA;

现在您的应用程序的内存如下所示:

内存图2

请注意,您的局部变量strB已更改,但对象和字符没有更改。

最后,您的代码执行此操作:

strA = @"StringA has been changed.";

这使您的应用程序的内存看起来像这样:

内存图3

您的局部变量strA已更改,但对象和字符仍未更改。

于 2012-07-18T21:01:41.910 回答
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是不同的对象。

我在这里想念什么?

我认为您认为在执行 assignment 时会创建新对象strB = strA;,但实际上在该语句之后两个指针都指向同一个对象。当您“更改”时strA,就会创建一个新对象。

现在,如果您谈论的是可变字符串,情况会有所不同,您当然可以更改。那么你会遇到这样的情况:

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
于 2012-07-18T20:35:37.917 回答
0

我的理解是说 strB = strA 意味着 strB 指向 strA 的内存位置,因此对 strA 的任何更改也会转到 strB。

更改 strA 的内存位置——是的。更改为指向同一位置的完全不相关的指针,该指针现在指向其他位置——不。

于 2012-07-18T20:34:16.023 回答
0

有两种方法可以考虑这里发生的事情。一个稍微低级的是,您正在处理一个称为指针的构造。int指针保存内存地址,与变量保存整数值的方式完全相同。如果将 an 分配int给 another int,则更改第一个,第二个不会更改:

int i1 = 10;
int i2 = i1;
i1 = 600;    // i2 still 10

指针也是如此。

另一种(可能更高效)的思考方式是,strA实际上strB是对象的名称。如果您通过一个名称将一个对象分配给另一个名称,则两个名称都包含同一个对象。抛开内存管理和对象生存期问题不谈,您可以将一个名称重新分配给不同的对象,而另一个名称将继续指向原始对象。

于 2012-07-18T20:42:09.963 回答