Difference between NSString literals

*爱你&永不变心* 提交于 2019-12-17 04:32:43

问题


What is the difference between these two lines?

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

回答1:


@"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.




回答2:


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.)




回答3:


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);
}



回答4:


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




回答5:


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.



来源:https://stackoverflow.com/questions/8032375/difference-between-nsstring-literals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!