Я изучаю Objective-C и Какао и наткнулся на это утверждение:
The Cocoa frameworks expect that global string constants rather than string literals are used for dictionary keys, notification and exception names, and some method parameters that take strings.
Я работал только с языками более высокого уровня, поэтому мне никогда не приходилось так подробно рассматривать детали строк. В чем разница между строковой константой и строковым литералом?





Давайте использовать C++, поскольку моей Objective C вообще не существует.
Если вы поместите строку в постоянную переменную:
const std::string mystring = "my string";
Теперь, когда вы вызываете методы, вы используете my_string, вы используете строковую константу:
someMethod(mystring);
Или вы можете вызвать эти методы напрямую со строковым литералом:
someMethod("my string");
Причина, по которой они, по-видимому, побуждают вас использовать строковые константы, заключается в том, что Objective C не выполняет «интернирование»; то есть, когда вы используете один и тот же строковый литерал в нескольких местах, это фактически другой указатель, указывающий на отдельную копию строки.
Для ключей словаря это имеет огромное значение, потому что, если я вижу, что два указателя указывают на одно и то же, это намного дешевле, чем проводить полное сравнение строк, чтобы убедиться, что строки имеют одинаковое значение.
Редактировать: Майк, в C# строки неизменяемы, а все буквальные строки с одинаковыми значениями заканчиваются на одно и то же строковое значение. Я полагаю, что это верно и для других языков, в которых есть неизменяемые строки. В Ruby, который имеет изменяемые строки, они предлагают новый тип данных: символы («foo» против: foo, где первая является изменяемой строкой, а вторая - неизменяемым идентификатором, часто используемым для ключей хеширования).
В Objective-C синтаксис @"foo" - это неизменный, буквальный экземпляр NSString. Он не создает постоянную строку из строкового литерала, как предполагает Майк.
Компиляторы Objective-C обычно делать внутренние литеральные строки в единицах компиляции - то есть они объединяют многократное использование одной и той же литеральной строки - и компоновщик может выполнять дополнительное интернирование между единицами компиляции, которые напрямую связаны в один двоичный файл. (Поскольку Какао различает изменяемые и неизменяемые строки, а буквальные строки всегда также неизменяемы, это может быть просто и безопасно.)
С другой стороны, строки Постоянный обычно объявляются и определяются с использованием такого синтаксиса:
// 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 имеет значение; оно гарантирует постоянство самого указателя.)
Хотя запись памяти не такая большая проблема, как это могло быть во времена рабочих станций 68030 с тактовой частотой 25 МГц и 8 МБ ОЗУ, сравнение строк на предмет равенства может занять время. Обеспечение того, чтобы в большинстве случаев равные строки также были равны указателям, помогает.
Скажем, например, вы хотите подписаться на уведомления от объекта по имени. Если вы используете непостоянные строки для имен, NSNotificationCenter, отправляющий уведомление, может закончить выполнение большого количества побайтовых сравнений строк при определении того, кто в этом заинтересован. Если большинство этих сравнений закорочены из-за того, что сравниваемые строки имеют один и тот же указатель, это может быть большим выигрышем.
«Программирование на Objective-C 2.0» не является справочником по языку; таким образом, цитировать его так, как если бы он был таковым, неверно. В C «foo» называется строковым литералом. Обычно «константа» относится к указателю или переменной, а не к литералу; литералы постоянны по определению.
Загорелась лампочка !! Постоянные строки полезны, когда вам нужна эффективность перечислений, но не нужны числа для значений. Отличный ответ, очень полезно !!
буквальный - это значение, которое по определению неизменяемо. например: 10
постоянный - это переменная или указатель только для чтения. например: const int age = 10;
строковый литерал - это выражение, подобное @"". Компилятор заменит это экземпляром NSString.
строковая константа - это указатель на NSString, доступный только для чтения. например: NSString *const name = @"John";
Некоторые комментарии к последней строке:
objc_sendMsg2 не волнует, квалифицируете ли вы объект как const. Если вам нужен неизменяемый объект, вы должны закодировать эту неизменяемость внутри объекта 3.@"" действительно неизменяемы. Они заменяются 4 во время компиляции экземплярами NSConstantString, который является специализированным подклассом NSString с фиксированной компоновкой памяти 5. Это также объясняет, почему NSString - единственный объект, который может быть инициализирован во время компиляции 6.постоянная строка будет const NSString* name = @"John";, что эквивалентно NSString const* name= @"John";. Здесь и синтаксис, и намерение программиста неверны: const <object> игнорируется, а экземпляр NSString (NSConstantString) уже был неизменным.
1 The keyword const applies applies to whatever is immediately to its left. If there is nothing to its left, it applies to whatever is immediately to its right.
2 This is the function that the runtime uses to send all messages in Objective-C, and therefore what you can use to change the state of an object.
3 Example: in const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const doesn't prevent the last statement.
4 The LLVM code that rewrites the expression is RewriteModernObjC::RewriteObjCStringLiteral in RewriteModernObjC.cpp.
5 To see the NSConstantString definition, cmd+click it in Xcode.
6 Creating compile time constants for other classes would be easy but it would require the compiler to use a specialized subclass. This would break compatibility with older Objective-C versions.
The Cocoa frameworks expect that global string constants rather than string literals are used for dictionary keys, notification and exception names, and some method parameters that take strings. You should always prefer string constants over string literals when you have a choice. By using string constants, you enlist the help of the compiler to check your spelling and thus avoid runtime errors.
Это говорит о том, что литералы подвержены ошибкам. Но это не говорит о том, что они медленнее. Сравнивать:
// string literal
[dic objectForKey:@"a"];
// string constant
NSString *const a = @"a";
[dic objectForKey:a];
Во втором случае я использую ключи с константными указателями, поэтому вместо [a isEqualToString:b] я могу использовать (a==b). Реализация isEqualToString: сравнивает хэш, а затем запускает функцию C strcmp, поэтому это медленнее, чем прямое сравнение указателей. Это почему постоянные строки лучше:, они быстрее сравниваются и менее подвержены ошибкам.
Если вы также хотите, чтобы ваша постоянная строка была глобальной, сделайте это следующим образом:
// header
extern NSString *const name;
// implementation
NSString *const name = @"john";
Майк прав. Из книги "Программирование в Objective-C 2.0" - "Строка @" Программирование в Objective-C - это весело. \ N "- пример объекта строки константных символов."