2009-01-20 7 views
40

J'ai vu du code autour de ces deux styles, je ne suis pas sûr si l'un est meilleur qu'un autre (est-ce juste une question de style)? Avez-vous des recommandations sur les raisons pour lesquelles vous choisiriez l'un plutôt qu'un autre?Définition de constantes de chaîne de classe en C++?

//Example1 
class Test { 

    private: 
     static const char* const str; 

}; 

const char* const Test::str = "mystr"; 

//Example2 
class Test { 

    private: 
     static const std::string str; 

}; 

const std::string Test::str ="mystr"; 
+1

comment cela est-il dérangeant? –

Répondre

55

Habituellement, vous devriez préférer std::string sur les pointeurs à char lisse. Ici, cependant, le pointeur char initialisé avec la chaîne littérale a un avantage significatif.

Il existe deux initialisations pour les données statiques. L'une est appelée initialisation statique et l'autre est appelée initialisation dynamique. Pour les objets qui sont initialisés avec des expressions constantes et qui sont des POD (comme des pointeurs), C++ exige que leur initialisation se produise au tout début, avant l'initialisation dynamique. L'initialisation d'une telle chaîne std :: sera faite dynamiquement. Si vous avez un objet d'une classe étant un objet statique dans un fichier, et que vous avez besoin d'accéder à la chaîne lors de son initialisation, vous pouvez compter sur elle déjà configurée lorsque vous utilisez la version const char* const, alors que en utilisant la version std::string, qui n'est pas initialisée statiquement, vous ne savez pas si la chaîne est déjà initialisée, car l'ordre d'initialisation des objets entre les limites d'unité de traduction n'est pas défini.

+7

+1 J'ai passé du temps à déboguer des plantages très méchants qui ont été provoqués par des instances statiques d'une classe de chaînes qui s'est cassée à cause de problèmes d'ordre d'initialisation. Évitez les instances statiques de 'std :: string'! –

+1

J'ai été très surpris par cette réponse. Est-il possible de le faire fonctionner avec std :: string? – loop

+0

@test: oui: 'std :: chaîne const & safe_string_const() {std :: chaîne statique const var =" const "; return var; } ' –

4

Hmmm, une chaîne std :: n'est pas la même chose qu'un const char *. J'utilise généralement std :: string parce que c'est une classe qui a de nombreuses fonctionnalités supplémentaires qui la rendent beaucoup plus facile à utiliser.

Si les performances sont primordiales et que vous utilisez constchar * pour l'efficacité, allez-y.

2

Le premier exemple nécessite moins de temps système pour la gestion de la chaîne (c'est-à-dire juste un pointeur vers la section TEXT). En outre, la deuxième méthode peut également nécessiter une allocation de tas pour copier la chaîne littérale dans le tampon de classe std: string. Donc, vous finiriez avec deux copies des données.

1

La seconde version a l'avantage d'avoir une longueur pré-calculée et les autres avantages d'une classe de cordes étoffée. La première présente l'avantage que la seule initialisation consiste simplement à assigner un pointeur aux données statiques déjà chargées dans l'image exécutable, où la seconde doit initialiser la chaîne à partir de ce même pointeur.

+0

La première version a strlen ... –

+0

Oui, mais c'est une opération O (n), donc en fonction de l'utilisation, cela peut être un problème. – Eclipse

+0

Mais je suppose que c'est juste un débat sur les avantages de std :: string vs char * en général. – Eclipse

3

J'ai tendance à privilégier les chaînes std :: string sur char * lorsque je fais du C++. Je préfère std :: string principalement pour ses capacités intégrées ainsi que la commodité et la sécurité de ne pas avoir à faire avec des pointeurs.

Cependant, comme d'autres l'ont mentionné, la version de const char * peut être favorable si vous êtes trop préoccupé par les performances. Il me semble me rappeler que quelqu'un d'intelligent a déclaré une fois que l'optimisation prématurée est la racine de tout mal (ou de quelque chose de ce genre). :)

2

Dans les grands projets impliquant plusieurs plates-formes avec différents compilateurs et bibliothèques, de nombreuses équipes, et beaucoup de gens, nous avons rencontré à plusieurs reprises des problèmes avec std :: strings statiques. Sur certaines plateformes, l'implémentation de std: string n'est pas sûre pour les threads. Sur une plate-forme, le code optimisé par le compilateur a été ignoré en initialisant une chaîne std: locale à partir de la const static statique. Après avoir résolu quelques-uns de ces problèmes, nous n'autorisons que les constats statiques globaux pour les types intégrés.

1

Tout d'abord, ne pas utiliser un caractère *.Si vous voulez une chaîne ASCIIZ, définir un d'entre eux directement:

const char Test::str[] = "mystr";

Pour la plupart, c'est ce que je l'utilise. Pourquoi perdre du temps et de la mémoire pour les frais généraux de la classe de cordes. Notez que "sizeof (Test :: str)" vous donnera précisément la longueur du tableau, qui est la longueur de la chaîne, y compris la fin NUL (strlen (str) +1).

+0

Bit étrange d'indiquer que std :: string gaspille de la mémoire lorsque vous perdez sizeof (Test :: str) en copiant un const const parfaitement bon [] à un autre const char []. – MSalters

+0

Qui copie quoi que ce soit? Est-ce que "const int x = 5;" copier quoi que ce soit? Il y a juste un char [] qui contient intrinsèquement la valeur "mystr"; –

Questions connexes