And why are str1 , str2 , str3 all located at different memory addresses? They are still immutable.
See bbum's comment here :
That's right ... one detail of the implementation of the relevant interest (but does not cancel the answer in any case); [[NSString alloc] initWithString:@"Hello world"] will not actually create a line on the heap. It will simply return the __NSCFConstantString compiler (or whatever it is called), which was laid down in the mach-o file by the compiler. This is just an interesting detail, since it does not change anything regarding your consumption of the mentioned line; it should be considered in the same way as any other object.
Emphasis on mine.
What happens here is that when the compiler, at compile time, can determine what an immutable NSString object will be, it creates this line in different ways. As bbum says, this is ultimately an implementation detail that you should not worry about when you write your program.
But a side effect of this means that the compiler is able to make my program more memory efficient, as it can find all of these instances and make all of my NSString pointers, which she knows should contain the same immutable value, point to the same same memory address.
We can probably achieve the same result with the following:
NSString *str1 = [[NSString alloc] init]; NSString *str2 = [NSString new]; NSString *str3 = [[NSString alloc] initWithString:@""]; NSString *str4 = [NSString stringWithString:@""]; NSString *str5 = @"";
This is all the same.
However, if we create another line:
NSString *str6 = [NSString stringWithFormat:@"%@", @""];
This will (most likely ... the last time I checked) end up with a different value if we print str6 as a pointer.
And there are other ways to generate immutable NSString objects that are not optimized this way at compile time. The point here is that if the compiler can find out what will be on this line at compile time, it will create an __NSCFConstantString in the background outside of memory management, and it will point to that single instance, whatever it is. Once it gets to runtime, it will point to something else if you specify it directly ( str6 = str1 ). Otherwise, he is not going to waste time executing, trying to determine if the lines are equal. If the new NSString is equal, and this did not happen at compile time, it will just be processed by ARC.
The compiler cannot determine that str6 is the same immutable string as the rest. It is just a build time value that the rest all have the same address.
Another interesting thing: you will never see a dealloc called by __NSCFConstantString that the compiler creates for variables declared the way you declared them. Therefore, the compiler not only makes your code more efficient in terms of memory, but also removes all the memory management code associated with maintaining these lines.