Pregunta

Estoy aprendiendo Objective-C y Cocoa y me encontré con esta afirmación:

Los marcos Cocoa esperan que se utilicen constantes de cadena globales en lugar de literales de cadena para claves de diccionario, nombres de notificaciones y excepciones, y algunos parámetros de métodos que toman cadenas.

Solo he trabajado en lenguajes de nivel superior, por lo que nunca tuve que considerar tanto los detalles de las cadenas.¿Cuál es la diferencia entre una cadena constante y una cadena literal?

¿Fue útil?

Solución

En Objective-C, la sintaxis @"foo" es un inmutable, literal en vez de NSString.No crea una cadena constante a partir de una cadena literal como supone Mike.

Los compiladores Objective-C normalmente hacer interna cadenas literales dentro de unidades de compilación, es decir, fusionan múltiples usos de la misma cadena literal, y es posible que el vinculador realice internaciones adicionales en las unidades de compilación que están directamente vinculadas en un único binario.(Dado que Cocoa distingue entre cadenas mutables e inmutables, y las cadenas literales también son siempre inmutables, esto puede ser sencillo y seguro).

Constante Por otro lado, las cadenas normalmente se declaran y definen usando una sintaxis como esta:

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

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

El objetivo del ejercicio sintáctico aquí es que puedes hacer usos de la cadena es eficiente al garantizar que solo haya una instancia de esa cadena en uso incluso en múltiples marcos (bibliotecas compartidas) en el mismo espacio de direcciones.(La colocación del const las palabras clave importan;garantiza que el puntero en sí será constante).

Si bien grabar memoria no es tan importante como lo hubiera sido en los días de las estaciones de trabajo 68030 de 25 MHz con 8 MB de RAM, comparar cadenas para determinar la igualdad puede llevar tiempo.Garantizar que la mayoría de las veces las cadenas que son iguales también serán de igual puntero.

Digamos, por ejemplo, que desea suscribirse a notificaciones de un objeto por su nombre.Si utiliza cadenas no constantes para los nombres, el NSNotificationCenter publicar la notificación podría terminar haciendo muchas comparaciones de cadenas byte por byte para determinar quién está interesado en ella.Si la mayoría de estas comparaciones tienen un cortocircuito porque las cadenas que se comparan tienen el mismo puntero, puede ser una gran ganancia.

Otros consejos

Algunas definiciones

A literal es un valor, que es inmutable por definición.p.ej: 10
A constante es una variable o puntero de solo lectura.p.ej: const int age = 10;
A literal de cadena es una expresión como @"".El compilador reemplazará esto con una instancia de NSString.
A constante de cadena es un puntero de sólo lectura a NSString.p.ej: NSString *const name = @"John";

Algunos comentarios sobre la última línea:

  • Ese es un puntero constante, no un objeto constante.1. objc_sendMsg2 No le importa si calificas el objeto con const.Si quieres un objeto inmutable, debes codificar esa inmutabilidad dentro del objeto.3.
  • Todo @"" Las expresiones son de hecho inmutables.son reemplazados4 en tiempo de compilación con instancias de NSConstantString, que es una subclase especializada de NSString con un diseño de memoria fijo5.Esto también explica por qué NSString es el único objeto que se puede inicializar en tiempo de compilación6.

A cadena constante sería const NSString* name = @"John"; que es equivalente a NSString const* name= @"John";.Aquí, tanto la sintaxis como la intención del programador son incorrectas: const <object> se ignora, y el NSString instancia (NSConstantString) ya era inmutable.

1 La palabra clave const se aplica se aplica a lo que esté inmediatamente a su izquierda.Si no hay nada a su izquierda, se aplica a lo que esté inmediatamente a su derecha.

2 Esta es la función que usa el tiempo de ejecución para enviar todos los mensajes en Objective-C y, por lo tanto, lo que puede usar para cambiar el estado de un objeto.

3 Ejemplo:en const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const no impide la última declaración.

4 El código LLVM que reescribe la expresión es RewriteModernObjC::RewriteObjCStringLiteral en RewriteModernObjC.cpp.

5 Ver el NSConstantString definición, cmd+clic en Xcode.

6 Crear constantes de tiempo de compilación para otras clases sería fácil, pero requeriría que el compilador utilice una subclase especializada.Esto rompería la compatibilidad con versiones anteriores de Objective-C.


Volver a tu cotización

Los marcos de cacao esperan que las constantes de cadena globales en lugar de los literales de cadena se usen para claves de diccionario, nombres de notificación y excepción, y algunos parámetros de método que toman cadenas.Siempre debe preferir constantes de cadena sobre literales de cadena cuando tenga una opción.Al usar constantes de cadena, solicita la ayuda del compilador para verificar su ortografía y, por lo tanto, evitar errores de tiempo de ejecución.

Dice que los literales son propensos a errores.Pero no dice que también sean más lentos.Comparar:

// string literal
[dic objectForKey:@"a"];

// string constant
NSString *const a = @"a";
[dic objectForKey:a];

En el segundo caso estoy usando claves con punteros constantes, por lo que en su lugar [a isEqualToString:b], Puedo hacer (a==b).La implementación de isEqualToString: compara el hash y luego ejecuta la función C strcmp, por lo que es más lento que comparar los punteros directamente.Cual es por qué las cadenas constantes son mejores: son más rápidos de comparar y menos propensos a errores.

Si también quieres que tu cadena constante sea global, hazlo así:

// header
extern NSString *const name;
// implementation
NSString *const name = @"john";

Usemos C++, ya que mi Objetivo C es totalmente inexistente.

Si guarda una cadena en una variable constante:

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

Ahora, cuando llamas a métodos, usas my_string, estás usando una constante de cadena:

someMethod(mystring);

O puede llamar a esos métodos con el literal de cadena directamente:

someMethod("my string");

La razón, presumiblemente, por la que lo alientan a usar constantes de cadena es porque Objective C no realiza "prácticas";es decir, cuando se utiliza el mismo literal de cadena en varios lugares, en realidad es un puntero diferente que apunta a una copia separada de la cadena.

Para las claves del diccionario, esto hace una gran diferencia, porque si puedo ver que los dos punteros apuntan a lo mismo, es mucho más barato que tener que hacer una comparación de cadenas completas para asegurarme de que las cadenas tengan el mismo valor.

Editar: Mike, en C# las cadenas son inmutables y las cadenas literales con valores idénticos terminan apuntando al mismo valor de cadena.Me imagino que eso también es cierto para otros idiomas que tienen cadenas inmutables.En Ruby, que tiene cadenas mutables, ofrecen un nuevo tipo de datos:símbolos ("foo" vs.:foo, donde la primera es una cadena mutable y la segunda es un identificador inmutable que se utiliza a menudo para claves Hash).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top