Разница между NSString литералами - PullRequest
15 голосов
/ 07 ноября 2011

В чем разница между этими двумя строками?

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

Ответы [ 5 ]

23 голосов
/ 07 ноября 2011

@ «Моя строка» - это буквенная строка, скомпилированная в двоичный файл. При загрузке он имеет место в памяти. Первая строка объявляет переменную, которая указывает на эту точку в памяти.

Из руководства по программированию строки:

Самый простой способ создать строковый объект в исходном коде - это использовать конструкция Objective-C @ "...":

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

Обратите внимание, что при создании строки таким образом, вы должны избегать использования чего-либо, кроме 7-битного Символы ASCII. Такой объект создается во время компиляции и существует на протяжении всего выполнения вашей программы. Компилятор делает такой объект константы уникальны для каждого модуля и никогда не освобождаются, хотя вы можете сохранить и освободить их, как и любой другой объект.

Вторая строка выделяет строку, беря эту буквальную строку. Обратите внимание, что обе строки @ "My String" одинаковы. Чтобы доказать это:

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

Выводит тот же адрес памяти:

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)

То, что говорят, это не только первые две строки с одним и тем же адресом памяти, но если вы не измените код, это один и тот же адрес памяти при каждом запуске. Это то же двоичное смещение в памяти. Но копия не только отличается, но и меняется каждый раз, когда вы ее запускаете, поскольку она размещается в куче.

Авторелиз не оказывает влияния в соответствии с приведенным выше документом. Вы можете освободить их, но они никогда не освобождаются. Таким образом, они равны не потому, что оба являются автоматически выдаваемой строкой, а в том, что они оба являются константами, а выпуск игнорируется.

6 голосов
/ 07 ноября 2011

Одна является литеральной строкой, которая сохраняется в течение жизни исполняемого приложения. Другой может быть динамическим объектом, который сохраняется только до автоматического освобождения. (Это может также быть буквальная строка, если система решит оптимизировать ее таким образом - нет никаких гарантий, что это не будет.)

2 голосов
/ 05 апреля 2013

Брайанмак на 100% прав в своем ответе.Я просто добавил явный пример, используя GHUnit .

NSString creation - литерал против нелитералов.

Показывает строки, созданные различными способами, если они являются литеральными или нелитеральными.

- (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);
}
1 голос
/ 07 ноября 2011

Разницы между ними нет. Строка, инициированная так, как вы показали в первом примере, является строкой с автоматическим освобождением.

0 голосов
/ 31 марта 2013

Просто запомните эту основную вещь: -

NSString *string = ...

Это указатель на объект, а не объект!

Следовательно, оператор: NSString *string = @"Hello"; присваивает адрес объекта @"Hello" строке указателя.

@"Hello" интерпретируется компилятором как постоянная строка, и сам компилятор выделяет для нее память.

Аналогично, устав

NSObject *myObject = somethingElse;

назначает адрес что-то еще для указателя myObject, и это somethingElse уже должно быть выделено при инициализации.

Следовательно, оператор: NSObject *myObject = [[NSObject alloc] init]; выделяет и инициализирует объект NSObject и присваивает его адрес myObject.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...