Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why dereferencing a NSString pointer is not necessary?

In the example

NSString *message = @"Hello";
message = @"World";

If message is just a pointer why don't I need to explicitly say whatever is in message is now equal to string or *message = @"World"; like in C?

like image 368
DWB Avatar asked Apr 09 '13 17:04

DWB


1 Answers

DISCLAIMER

The discussion below gives a general idea on why you never dereferenciate a pointer to an object in Objective-C. However, concerning the specific case of NSString literals, this is not what's happening in reality. While the structure described below is still sound and it may work that way, what's actually happening is that the space for a string literal is allocated at compile time, and you get its address back. This is true for string literals, since they are immutable and constant. For the sake of efficiency therefore each literal is allocated only once.

As a matter of fact

NSString * a = @"Hello";
NSString * b = @"Hello";
NSLog(@"%@ %p", a, a); // Hello 0x1f4958
NSLog(@"%@ %p", b, b); // Hello 0x1f4958

ORIGINAL ANSWER

Because it will be translated to

message = [[NSString alloc] initWithUTF8String:"Hello"]];

which will boil down to

message = objc_msgSend(objc_msgSend(objc_getClass("NSString"), @selector(alloc)), @selector(initWithUTF8String:), "Hello");

Now if we take a look to the signature of objc_msgSend

id objc_msgSend(id theReceiver, SEL theSelector, ...)

we see that the method returns an id type, which in Objective-C is the object type. But how is id actually defined?

typedef struct objc_object {
    Class isa;
} *id;

id is defined as a pointer to an objc_object struct.

So in the end @"string" will translate in a function call that will produce a pointer to an object (i.e. an objc_object struct, if you prefer), which is exactly what you need to assign to message.

Bottom line, you assign pointers, not objects.

To better clarify the last concept consider this

NSMutableString * a = [NSMutableString stringWithString:@"hello"];
NSMutableString * b = a;
[a setString:@"hola"];
NSLog(@"%@", a); // "hola"
NSLog(@"%@", b); // "hola"

If you were assigning objects, b would have been a copy of a and any further modification of a wouldn't have affected b.

Instead what you get is a and b being two pointers to the same object in the heap.

like image 59
Gabriele Petronella Avatar answered Sep 24 '22 03:09

Gabriele Petronella