Difference between these two NSString methods
Asked Answered
C

5

7

So I just got asked this at an interview today and after some googling am still unable to figure out the answer (in fact I couldn't even find any code at all which used the [NSString string] method).

What is the difference between

  1. NSString *someString = [NSString string];
  2. NSString *someString = [[NSString alloc] init];

Now my initial thoughts were that [NSString string] would return an object which would be autoreleased whereas using alloc and init would return an object which has been retained. However it seems that this answer was incorrect.

I've looked at the NSString class reference in the apple docs but all it says is

Returns an empty string.

+ (id)string 

Return Value
An empty string.

Could somebody explain to me exactly what the difference between these two are?

Chaeta answered 26/10, 2011 at 8:42 Comment(3)
Seems a bit unfair if that's the only reason you didn't get the job.Sonorant
In iOS5 (with ARC) they are the same things.Shortening
@Sonorant This was just one of the many questions I got asked, I don't think it'll be the sole reason on whether or not I proceed past this interview stageChaeta
F
4

Now my initial thoughts were that [NSString string] would return an object which would be autoreleased

Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution, never being released. It’s not an autoreleased string. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is not owned by the caller, hence the caller shouldn’t release it.

whereas using alloc and init would return an object which has been retained

Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution. In fact, it’s the same object as the one above, and it is not retained. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is owned by the caller, hence the caller is responsible for releasing it when it’s not needed any longer.

Fanestil answered 26/10, 2011 at 8:56 Comment(1)
Since this was a question regarding interviews, I'll mark this as the correct answer as it seems to explain what the answer an interviewer would be expecting. Thanks BevariousChaeta
V
5

Was that your response, and did you ask why your answer was incorrect? I ask because your assumption is mostly correct (at a higher level).

It's not exactly 'retained' when returned from alloc+init, it is an object you hold one reference to, and should balance with a release or autorelease. For the convenience constructor (+[NSString string]), you are returned an object which you hold zero references to, but one which you can expect to live until the current autorelease pool is popped unless you send it an explicit retain (assuming MRC or ARC, since it is tagged iOS).

At the lower level, you could make some guesses, but I wouldn't expect that question in many objc interviews (unless you told them you were mid or senior level). Basically, it is implementation defined, but both forms could return the same static, constant NSString (that may have been what the interviewer was looking for). To illustrate:

@implementation NSString

static NSString * const EmptyNSString = @"";

- (id)init
{
    self = [super init];
    [self release];
    return EmptyNSString;
}

+ (id)string
{
    return EmptyNSString;
}

...

Again, that's implementation defined, but an obvious optimization. As well, that optimization makes physically subclassing concrete immutable types (NSString) difficult for mutable variants (NSMutableString) in some cases.

Vereen answered 26/10, 2011 at 8:49 Comment(5)
Thanks for the response justin, I didn't actually ask if it was incorrect as we were running a bit short on time with the interview, but they asked me if I was sure my answer was correct and told me to look at the question again and I gave them a puzzled look then we moved on.Chaeta
@Chaeta Ah, ok. So the question may or may not have been answered satisfactorily, and they wanted to know whether you knew of the optimization I outlined (or perhaps something else).Vereen
@JeremyP Why not? ...or were you referring to a point I clarified in an edit?Vereen
@Justin: see my answer for why not. However, on rereading your answer, I think my down vote was harsh, so I am removing it.Prissy
@Prissy alright, there were a few points i worded poorly along the way and updated after i realized that so...Vereen
F
4

Now my initial thoughts were that [NSString string] would return an object which would be autoreleased

Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution, never being released. It’s not an autoreleased string. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is not owned by the caller, hence the caller shouldn’t release it.

whereas using alloc and init would return an object which has been retained

Technically, it’s a placeholder string that is constant, i.e., it lives throughout the entire program execution. In fact, it’s the same object as the one above, and it is not retained. Conceptually, and this is what I’d focus as an interviewer, it’s a string (an empty string) that is owned by the caller, hence the caller is responsible for releasing it when it’s not needed any longer.

Fanestil answered 26/10, 2011 at 8:56 Comment(1)
Since this was a question regarding interviews, I'll mark this as the correct answer as it seems to explain what the answer an interviewer would be expecting. Thanks BevariousChaeta
P
4

The correct answer is that

NSString *someString = [NSString string];

gives you an empty string that you do not own and that you must not release (according to the memory management rules)

whereas

NSString *someString = [[NSString alloc] init];

gives you an empty string you do own and that you must release (according to the memory management rules).

Without poking into the implementation, you can't say anything else about those two strings. You can't say that they are autoreleased, because they might not be and you can't say what the retain count will be.

In actual fact, you'll probably get (in both cases) the same pointer to a constant object of some NSString subclass, probably with a retain count of UINT_MAX which is used by the run time as a flag to disable normal retain release behaviour for constant strings. I haven't actually tried the above because nobody except the maintainers of the Objective-C SDK needs to care.

Prissy answered 26/10, 2011 at 9:4 Comment(3)
Thanks for the response Jeremy and letting me know about the UINT_MAX flagChaeta
@Jason: the UINT_MAX thing is an implementation detail. You don't need to know about it normally.Prissy
Yep, I understand that, but maybe it's just a pet peeve of mine, but I like to know about these little intricate details that you don't usually learn from reading textbooksChaeta
D
0

You don't often see

NSString *someString = [NSString string]; 

because it's the same as

NSString *someString = @""; 

which is shorter. It's usually used to create an empty NSMutableString

NSMutableString* s = [NSMutableString string];
Digiovanni answered 26/10, 2011 at 8:53 Comment(6)
Do both those statements actually have the exact same meaning, no funny stuff going on in the background? I ask because I'm curious as to why the NSString class would have a string method which would never realistically be used?Chaeta
Note that the constant empty string returned by +[NSString string] is not the same object as @"".Fanestil
It's usefull in the case of NSMutableString* s = [NSMutableString string];Digiovanni
Could the person who downvoted kindly explain any circumstance where NSString *someString = [NSString string]; actually behaves differently to NSString *someString = @"";Digiovanni
[NSString string] is an autoreleased empty string, so is @"" (in any case you can think of it that way, even if "technically", "under the hood", it's not the case, that's an implementation detail).Digiovanni
Neither is autoreleased. Also, your answer doesn’t show a downvote. O_oFanestil
L
0

The only thing I can imagine is that:

  1. Won't allocate memory since it is not made with alloc. It is a constant (an empty string) made by the system and doesn't need to be released.

  2. You allocate the memory for the NSString yourself which means you have to keep track if the NSString still 'lives' or not when you are done with it, and thus need to release it.

Lishalishe answered 26/10, 2011 at 8:57 Comment(1)
Even +[NSString alloc] doesn’t allocate memory — it returns a placeholder singleton of type NSPlaceholderString. It’s a common pattern when implementing class clusters.Fanestil

© 2022 - 2024 — McMap. All rights reserved.