Сведения о вопросе

None

22:56, 14th August, 2020

Теги

objective-c   string    

В чем разница между Строковой константой и строковым литералом?

Просмотров: 514   Ответов: 3

Я изучаю objective-C и Cocoa и наткнулся на это утверждение:

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

Я работал только на языках более высокого уровня, поэтому мне никогда не приходилось так много рассматривать детали строк. В чем разница между Строковой константой и строковым литералом?



  Сведения об ответе

KOMP

13:09, 2nd August, 2020

В Objective-C синтаксис @"foo" является неизменяемым, буквальным экземпляром NSString . Это не делает постоянную строку из строкового литерала, как предполагают Майки.

Цель-компиляторы C обычно интернируют литеральные строки в единицах компиляции — то есть они объединяют многократное использование одной и той же литеральной строки — и компоновщик может выполнить дополнительное интернирование между единицами компиляции, которые непосредственно связаны в один двоичный файл. (Поскольку Cocoa различает изменяемые и неизменяемые строки, а литеральные строки всегда также неизменяемы, это может быть простым и безопасным.)

Константные строки с другой стороны обычно объявляются и определяются с помощью такого синтаксиса:

// MyExample.h - declaration, other code references this
extern NSString * const MyExampleNotification;

// MyExample.m - definition, compiled for other code to reference
NSString * const MyExampleNotification = @"MyExampleNotification";

Смысл синтаксического упражнения здесь заключается в том, что вы можете эффективно использовать строку, гарантируя, что даже в нескольких фреймворках (общих библиотеках) в одном адресном пространстве используется только один экземпляр этой строки. (Размещение ключевого слова const имеет значение; это гарантирует, что сам указатель гарантированно будет постоянным.)

Хотя сжигание памяти не так важно, как это могло бы быть в дни рабочих станций 25MHz 68030 с 8MB RAM, сравнение строк для равенства может занять некоторое время. Обеспечение того, что большинство строк времени, которые равны, также будут равны указателю, помогает.

Скажем, например, вы хотите подписаться на уведомления от объекта по имени. Если вы используете непостоянные строки для имен, то NSNotificationCenter , отправляющий уведомление, может в конечном итоге сделать много сравнений строк byte-by-byte при определении того, кто в нем заинтересован. Если большинство этих сравнений будут короткими, потому что сравниваемые строки имеют один и тот же указатель, это может быть большой выигрыш.


  Сведения об ответе

PHPH

23:50, 28th August, 2020

Некоторые определения

Литерал - это значение, которое является неизменяемым по определению. например: 10
Константа - это переменная или указатель только для чтения. например: const int age = 10;
Строковый литерал - это выражение типа @"" . Компилятор заменит его экземпляром NSString .
Строковая константа - это указатель только для чтения на NSString . например: NSString *const name = @"John";

Некоторые комментарии к последней строке:

  • Это постоянный указатель, а не постоянный объект 1 . objc_sendMsg 2 не имеет значения, если вы квалифицируете объект с помощью const . Если вам нужен неизменяемый объект, вы должны закодировать эту неизменяемость внутри объекта 3 .
  • Все выражения @"" действительно неизменны. Они заменяются 4 во время компиляции экземплярами NSConstantString, который является специализированным подклассом NSString с фиксированным расположением памяти 5 . Это также объясняет, почему NSString является единственным объектом, который может быть инициализирован во время компиляции 6 .

Постоянная строка будет иметь значение const NSString* name = @"John"; , что эквивалентно NSString const* name= @"John"; . Здесь и синтаксис, и намерение программиста ошибочны: const <object> игнорируется, а экземпляр NSString ( NSConstantString ) уже был неизменяемым.

1 ключевое слово const applies относится к тому, что находится непосредственно слева от него. Если слева от него ничего нет, он обращается ко всему, что находится непосредственно справа.


  Сведения об ответе

fo_I_K

18:44, 15th August, 2020

Давайте использовать C++, так как моя цель C совершенно не существует.

Если вы прячете строку в постоянную переменную:

const std::string mystring = "my string";

Теперь, когда вы вызываете методы, вы используете my_string, вы используете строковую константу:

someMethod(mystring);

Или же вы можете вызвать эти методы с помощью строкового литерала напрямую:

someMethod("my string");

Причина, по-видимому, в том, что они поощряют вас использовать строковые константы, заключается в том, что Objective C не делает "interning"; то есть, когда вы используете один и тот же строковый литерал в нескольких местах, это фактически другой указатель, указывающий на отдельную копию строки.

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

Edit: Mike, в C# строки являются неизменяемыми, а литеральные строки с одинаковыми значениями все заканчиваются указывая на одно и то же строковое значение. Я полагаю, что это верно и для других языков, которые имеют неизменяемые строки. В Ruby, который имеет изменяемые строки, они предлагают новый тип данных: символы ("foo" vs.: foo, где первый является изменяемой строкой, а второй-неизменяемым идентификатором, часто используемым для ключей Hash).


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться