Quelle est la différence entre une constante de chaîne et une chaîne littérale ?

StackOverflow https://stackoverflow.com/questions/25746

  •  09-06-2019
  •  | 
  •  

Question

J'apprends Objective-C et Cocoa et je suis tombé sur cette déclaration :

Les frameworks Cocoa s'attendent à ce que des constantes de chaîne globales plutôt que des chaînes littérales soient utilisées pour les clés de dictionnaire, les noms de notification et d'exception, ainsi que certains paramètres de méthode qui acceptent des chaînes.

Je n'ai travaillé que dans des langages de niveau supérieur, je n'ai donc jamais eu à trop considérer les détails des chaînes.Quelle est la différence entre une constante de chaîne et une chaîne littérale ?

Était-ce utile?

La solution

En Objective-C, la syntaxe @"foo" est un immuable, littéral exemple de NSString.Cela ne crée pas une chaîne constante à partir d’une chaîne littérale comme le suppose Mike.

Compilateurs Objective-C généralement faire chaînes littérales internes au sein des unités de compilation (c'est-à-dire qu'elles fusionnent plusieurs utilisations de la même chaîne littérale) et il est possible pour l'éditeur de liens d'effectuer un internement supplémentaire entre les unités de compilation qui sont directement liées en un seul binaire.(Puisque Cocoa fait la distinction entre les chaînes mutables et immuables et que les chaînes littérales sont toujours également immuables, cela peut être simple et sûr.)

Constante les chaînes, en revanche, sont généralement déclarées et définies en utilisant une syntaxe comme celle-ci :

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

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

Le but de l’exercice syntaxique ici est que vous pouvez faire utilisations de la chaîne efficace en garantissant qu'il n'y a qu'une seule instance de cette chaîne en cours d'utilisation même dans plusieurs frameworks (bibliothèques partagées) dans le même espace d’adressage.(L'emplacement du const les mots clés sont importants ;cela garantit que le pointeur lui-même est garanti constant.)

Même si graver de la mémoire n'est pas aussi grave qu'à l'époque des stations de travail 68030 à 25 MHz avec 8 Mo de RAM, comparer les chaînes pour vérifier l'égalité peut prendre du temps.S'assurer que la plupart du temps, les chaînes qui sont égales seront également des aides égales au pointeur.

Supposons, par exemple, que vous souhaitiez vous abonner aux notifications d'un objet par son nom.Si vous utilisez des chaînes non constantes pour les noms, le NSNotificationCenter la publication de la notification pourrait entraîner de nombreuses comparaisons de chaînes octet par octet pour déterminer qui est intéressé.Si la plupart de ces comparaisons sont court-circuitées parce que les chaînes comparées ont le même pointeur, cela peut être une grande victoire.

Autres conseils

Quelques définitions

UN littéral est une valeur immuable par définition.par exemple: 10
UN constante est une variable ou un pointeur en lecture seule.par exemple: const int age = 10;
UN chaîne littérale est une expression comme @"".Le compilateur le remplacera par une instance de NSString.
UN constante de chaîne est un pointeur en lecture seule vers NSString.par exemple: NSString *const name = @"John";

Quelques commentaires sur la dernière ligne :

  • C'est un pointeur constant, pas un objet constant1. objc_sendMsg2 peu importe si vous qualifiez l'objet avec const.Si vous voulez un objet immuable, vous devez coder cette immuabilité à l'intérieur de l'objet3.
  • Tous @"" les expressions sont en effet immuables.Ils sont remplacés4 au moment de la compilation avec des instances de NSConstantString, qui est une sous-classe spécialisée de NSString avec une disposition de mémoire fixe5.Cela explique aussi pourquoi NSString est le seul objet qui peut être initialisé au moment de la compilation6.

UN chaîne constante serait const NSString* name = @"John"; ce qui équivaut à NSString const* name= @"John";.Ici, la syntaxe et l'intention du programmeur sont fausses : const <object> est ignoré, et le NSString exemple (NSConstantString) était déjà immuable.

1 Le mot clé const apply s'applique à tout ce qui se trouve immédiatement à sa gauche.S'il n'y a rien à sa gauche, cela s'applique à tout ce qui se trouve immédiatement à sa droite.

2 C'est la fonction que le runtime utilise pour envoyer tous les messages en Objective-C, et donc ce que vous pouvez utiliser pour changer l'état d'un objet.

3 Exemple:dans const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const n'empêche pas la dernière instruction.

4 Le code LLVM qui réécrit l'expression est RewriteModernObjC::RewriteObjCStringLiteral dans RewriteModernObjC.cpp.

5 Pour voir le NSConstantString définition, cmd+cliquez dessus dans Xcode.

6 Créer des constantes de temps de compilation pour d'autres classes serait facile mais cela nécessiterait que le compilateur utilise une sous-classe spécialisée.Cela romprait la compatibilité avec les anciennes versions d'Objective-C.


Retour à votre devis

Les cadres de cacao s'attendent à ce que les constantes de chaîne globales plutôt que les littéraux de chaîne soient utilisées pour les clés de dictionnaire, les noms de notification et d'exception, et certains paramètres de méthode qui prennent des chaînes.Vous devez toujours préférer les constantes de chaîne aux littéraux de chaîne lorsque vous avez le choix.En utilisant des constantes de chaîne, vous enrôlez l'aide du compilateur pour vérifier votre orthographe et évitez ainsi les erreurs d'exécution.

Cela dit que les littéraux sont sujets aux erreurs.Mais cela ne dit pas qu’ils sont aussi plus lents.Comparer:

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

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

Dans le deuxième cas, j'utilise des clés avec des pointeurs const, donc à la place [a isEqualToString:b], Je peux faire (a==b).L'implémentation de isEqualToString: compare le hachage puis exécute la fonction C strcmp, c'est donc plus lent que de comparer directement les pointeurs.Lequel est pourquoi les chaînes constantes sont meilleures : ils sont plus rapides à comparer et moins sujets aux erreurs.

Si vous souhaitez également que votre chaîne constante soit globale, procédez comme ceci :

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

Utilisons C++, puisque mon Objective C est totalement inexistant.

Si vous cachez une chaîne dans une variable constante :

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

Désormais, lorsque vous appelez des méthodes, vous utilisez my_string, vous utilisez une constante chaîne :

someMethod(mystring);

Ou bien, vous pouvez appeler ces méthodes directement avec la chaîne littérale :

someMethod("my string");

La raison, probablement, pour laquelle ils vous encouragent à utiliser des constantes de chaîne est que Objective C ne fait pas de "stage" ;autrement dit, lorsque vous utilisez la même chaîne littérale à plusieurs endroits, il s'agit en fait d'un pointeur différent pointant vers une copie distincte de la chaîne.

Pour les clés de dictionnaire, cela fait une énorme différence, car si je peux voir que les deux pointeurs pointent vers la même chose, cela revient beaucoup moins cher que de devoir faire une comparaison de chaînes entières pour s'assurer que les chaînes ont la même valeur.

Modifier: Mike, en C#, les chaînes sont immuables et les chaînes littérales avec des valeurs identiques se terminent toutes par la même valeur de chaîne.J'imagine que cela est également vrai pour d'autres langages qui ont des chaînes immuables.Dans Ruby, qui possède des chaînes mutables, ils proposent un nouveau type de données :symboles ("foo" vs.:foo, où la première est une chaîne mutable et la seconde un identifiant immuable souvent utilisé pour les clés de hachage).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top