Reputation: 37
I did find some discussion on this topic, but it was beyond my current level of understanding. I'm reading through Kochan's "Programming in Objective-C, 4e" and am on the section about NSString objects. First, the code I'm playing with so I can ask my question:
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"
My understanding is that saying strB = strA would mean that strB is pointing to strA's memory location, so any changes to strA would also go to strB. However, this doesn't happen. Kochan says it's supposed to, and to get around it suggests using
strB = [NSString stringWithString: strA];
From what I can see, either method works. I can say strB = strA, then change strA, yet strB still retains the value it received (the value of strA before just changing it).
I thought this might come from NSString being immutable, but if that's the case, why can I in fact change the values of str1 and str2 after initialization? What am I missing here? Thanks.
Upvotes: 0
Views: 255
Reputation: 385580
As if you didn't have enough answers to this already...
I think a diagram or three will help you understand what's going on in your code example.
First, your code does this:
NSString *strA = @"StringA";
NSString *strB = @"StringB";
This makes your app's memory look like this:
On the left are your local variables, strA
and strB
. They are just pointers to objects in memory.
In the middle are the string objects. These are pre-created in your app by the compiler because they appeared in your source code.
On the right are the actual characters of the string objects. These are also pre-created in your app by the compiler.
Next, your code does this:
strB = strA;
Now your app's memory looks like this:
Notice that your local variable, strB
, changed, but the objects and the characters didn't change.
Finally, your code does this:
strA = @"StringA has been changed.";
This makes your app's memory look like this:
Your local variable, strA
, has changed, but the objects and the characters still didn't change.
Upvotes: 3
Reputation: 124997
My understanding is that saying strB = strA would mean that strB is pointing to strA's memory location, so any changes to strA would also go to strB.
Yes, although it might be more clear to say that strB
and strA
will both point to the same object.
I can say strB = strA, then change strA, yet strB still retains the value it received (the value of strA before just changing it).
If you change strA
, then you're necessarily making strA
point to a different string. NSStrings are immutable, so you can't change them -- you can only replace them. So, if you say something like:
strA = [strA stringByAppendingString:@"foo"];
then strA
no longer points to the original string. strB
still points to the original, of course, and that object remains unchanged, so the string pointed to by strA
and the one pointed to by strB
are different objects.
What am I missing here?
I think you're thinking that the new object is created when you do the assignment strB = strA;
, but in reality both pointers will point to the same object after that statement. It's when you "change" strA
that a new object is created.
Now, things would be different if you were talking about mutable strings, which you can of course change. Then you'd have a situation like this:
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
Upvotes: 1
Reputation: 64002
There's two ways to think about what's happening here. One, slightly more low-level, is that you're dealing with a construct called a pointer. A pointer holds a memory address, in exactly the same way that an int
variable holds an integer value. If you assign an int
to another int
, then change the first, the second does not change:
int i1 = 10;
int i2 = i1;
i1 = 600; // i2 still 10
The same is true of pointers.
The other (possibly more productive) way to think of it is that strA
and strB
are actually names for objects. If you assign an object via one name to another name, then both names hold the same object. Issues of memory management and object lifetime aside, you can then re-assign one name to a different object, and the other will continue to point to the original object.
Upvotes: 0
Reputation:
My understanding is that saying strB = strA would mean that strB is pointing to strA's memory location, so any changes to strA would also go to strB.
Changes to strA's memory location -- yes. Changes to a completely unrelated pointer to the same location, which now points to somewhere else -- no.
Upvotes: 0