xonegirlz
xonegirlz

Reputation: 8977

Difference between NSString literals

What is the difference between these two lines?

NSString * string = @"My String";
NSString * string = [[[NSString alloc] initWithString:@"MyString"] autorelease]

Upvotes: 17

Views: 8025

Answers (5)

mmorris
mmorris

Reputation: 4016

bryanmac is 100% correct in his answer. I just added an explicit example using GHUnit.

NSString creation - literal vs nonliteral.

Shows strings created in various ways if they are literal nor nonliteral.

- (void) test_stringCreation
{
    NSString *literalString = @"literalString";
    NSString *referenced = literalString;
    NSString *copy = [literalString copy];
    NSString *initWithString = [[NSString alloc] initWithString:literalString];
    NSString *initWithFormat = [[NSString alloc] initWithFormat:@"%@", literalString];

    // Testing that the memory addresses of referenced objects are the same.
    GHAssertEquals(literalString, @"literalString", @"literal");
    GHAssertEquals(referenced, @"literalString", @"literal");
    GHAssertEquals(copy, @"literalString", @"literal");
    GHAssertEquals(initWithString, @"literalString", @"literal");
    GHAssertNotEquals(initWithFormat, @"literalString",
                      @"nonliteral - referenced objects' memory addresses are \
                      different.");

    // Testing that the objects referenced are equal, i.e. isEqual: .
    GHAssertEqualObjects(literalString, @"literalString", nil);
    GHAssertEqualObjects(referenced, @"literalString", nil);
    GHAssertEqualObjects(copy, @"literalString", nil);
    GHAssertEqualObjects(initWithString, @"literalString", nil);
    GHAssertEqualObjects(initWithFormat, @"literalString", nil);

    // Testing that the strings referenced are the same, i.e. isEqualToString: .
    GHAssertEqualStrings(literalString, @"literalString", nil);
    GHAssertEqualStrings(referenced, @"literalString", nil);
    GHAssertEqualStrings(copy, @"literalString", nil);
    GHAssertEqualStrings(initWithString, @"literalString", nil);
    GHAssertEqualStrings(initWithFormat, @"literalString", nil);
}

Upvotes: 2

Burhanuddin Sunelwala
Burhanuddin Sunelwala

Reputation: 5343

Just remember this basic thing:-

NSString *string = ...

This is a pointer to an object, "not an object"!

Therefore, the statement: NSString *string = @"Hello"; assigns the address of @"Hello" object to the pointer string.

@"Hello" is interpreted as a constant string by the compiler and the compiler itself allocates the memory for it.

Similarly, the statment

NSObject *myObject = somethingElse;

assigns the address of somethingElse to pointer myObject, and that somethingElse should already be allocated ad initialised.

Therefore, the statement: NSObject *myObject = [[NSObject alloc] init]; allocates and initializes a NSObject object and assigns its address to myObject.

Upvotes: 0

bryanmac
bryanmac

Reputation: 39296

@"My String" is a literal string compiled into the binary. When loaded, it has a place in memory. The first line declares a variable that points to that point in memory.

From the string programming guide:

The simplest way to create a string object in source code is to use the Objective-C @"..." construct:

NSString *temp = @"/tmp/scratch"; 

Note that, when creating a string constant in this fashion, you should avoid using anything but 7-bit ASCII characters. Such an object is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated, though you can retain and release them as you do any other object.

The second line allocates a string by taking that literal string. Note that both @"My String" literal strings are the same. To prove this:

NSString *str = @"My String";
NSLog(@"%@ (%p)", str, str);

NSString *str2 = [[NSString alloc] initWithString:@"My String"];
NSLog(@"%@ (%p)", str2, str2);

NSString *copy = [str2 stringByAppendingString:@"2"];
NSLog(@"%@ (%p)", copy, copy);

Outputs the same memory address:

2011-11-07 07:11:26.172 Craplet[5433:707] My String (0x100002268)
2011-11-07 07:11:26.174 Craplet[5433:707] My String (0x100002268)
2011-11-07 07:11:26.174 Craplet[5433:707] My String2 (0x1003002a0)

What's telling is not only are the first two string the same memory address, but if you don't change the code, it's the same memory address every time you run it. It's the same binary offset in memory. But, not only is the copy different but it's different every time you run it since it's allocated on the heap.

The autorelease has no affect according to the doc ref above. You can release them but they are never deallocated. So, they are equal not because both are autoreleased string but that they're both constants and the release is ignored.

Upvotes: 24

Hot Licks
Hot Licks

Reputation: 47729

One is a literal string, which persists for the life of the executing app. The other may be a dynamic object that only persists until autoreleased. (It may also be a literal string, if the system decides to optimize it that way -- there are no guarantees it won't.)

Upvotes: 6

Michael Frederick
Michael Frederick

Reputation: 16714

There is no difference between them. A string initiated how you showed in the first example is an autoreleased string.

Upvotes: 1

Related Questions