48 votes

Est-il mauvais de dépendre de l'index 0 d'un std :: string vide?

std::string my_string = "";
char test = my_string[0];

J'ai remarqué que cela ne plante pas, et à chaque fois que je l'ai testé, test est de 0.

Puis-je en dépendent toujours de 0? ou est-il arbitraire?

Est-ce la mauvaise programmation?

Edit: De certains commentaires, je comprends que ces est un malentendu à propos de l'utilité de cette.

Le but n'est PAS de vérifier pour voir si la chaîne est vide. C'est pour ne pas avoir besoin de vérifier si la chaîne est vide.

La situation est qu'il n'y est une chaîne qui peut ou ne peut pas être vide. Je ne se soucient que le premier caractère de cette chaîne (si elle n'est pas vide).

Il me semble, il serait moins efficace pour vérifier si la chaîne est vide, et puis, si elle n'est pas vide, à regarder le premier caractère.

Au lieu de cela, je peux juste regarder le premier personnage sans avoir besoin de vérifier pour voir si la chaîne est vide.

69voto

Bartek Banachewicz Points 13173

C++14

Non; vous pouvez compter sur elle.

Dans 21.4.5.2 (ou [string.accès]), nous pouvons trouver:

Retourne: *(begin() + pos) si pos < size(). Sinon, retourne une référence vers un objet de type charT valeur charT(), d'où la modification de l'objet conduit à un comportement indéfini.

En d'autres termes, lorsqu' pos == size() (ce qui est vrai lorsque les deux sont à 0), l'opérateur retourne une référence à un défaut construit le type de caractère qui vous est interdit de modifier.

Il n'est pas spéciale-étui pour le vide (ou 0-taille) les chaînes de caractères et fonctionne de la même pour toutes les longueurs.


C++03

Et très certainement, C++98.

Il dépend.

Voici 21.3.4.1 de l'officiel ISO/IEC 14882:

Retourne: Si pos < size(), les retours data()[pos]. Si, au contraire, pos == size(), la version const retourne le diagramme (le). Sinon, le comportement est indéfini.

31voto

einpoklum Points 2893

@Bartek Banachewicz la réponse explique quand vous pouvez faire votre hypothèse. Je tiens à ajouter que:

C'est une mauvaise programmation.

Pourquoi? Pour plusieurs raisons:

  1. Vous avez à être une langue avocat juste pour être sûr que ce n'est pas un bug. Je ne sais pas si ce n'est pour l'autre réponse, et franchement, je ne pense pas que vous avez vraiment pris la peine de savoir.
  2. Les gens sans avoir l'intuition d'une chaîne se terminant par null séquence de caractères n'ont aucune idée de ce que vous essayez de faire, jusqu'à ce qu'ils lisent la norme ou de demander à leurs amis.
  3. Rompt le principe de moindre surprise dans le mauvais sens.
  4. Va à l'encontre du principe de la "écrire ce que vous voulez dire", c'est à dire ayant le code express problème-domaine des concepts.
  5. Sorte de l'utilisation d'un nombre magique (on peut se demander si 0 constitue en fait un nombre magique dans ce cas).

Dois je continuer? ... Je suis à 99% sûr que vous avez une alternative supérieure à presque tous les égards. Je suis même 66% convaincu que vous avez fait quelque chose d'autre qui est "mauvais" pour manipuler vous-même en vouloir pour cela.

Rappelez-vous toujours: d'Autres personnes, qui ne sera pas vous consulter, aura tôt ou tard besoin de maintenir ce code. Pensez à eux, pas seulement de vous-même, qui peut le comprendre. De Plus, dans une dizaine d'années à partir de maintenant, qui est-à-dire que vous allez vous souvenir de votre propre truc? Vous pourriez être qu'confondus responsable...

3voto

cmaster Points 7460

Les autres réponses ont donné à la langue de l'avocat de réponses au sujet de ce que vous ne pouvez pas compter sur. Ceux qui sont du bon et du vrai, et je ne vais pas le répéter. Je vais donner une réponse sur la façon dont vous pouvez obtenir l'effet observé de manière sécurisée.

La solution est simple: il suffit d'insérer un appel à l' c_str():

std::string my_string = "";
char test = my_string.c_str()[0];
assert(test == 0);

ou plus directement:

const char* my_string = "";
char test = my_string[0];
assert(test == 0);

C'est sûr, parce que le C-style chaînes sont garantis d'être terminées par un zéro, de sorte que le pointeur résultant d'un c_str() appel ou C-littéral de chaîne doit pointer vers un tableau d'au moins un octet. Pour une chaîne vide, qui sera toujours la résiliation de zéro octet.

Bien sûr, ce c_str() truc est mauvais style à la valeur nominale. Cependant, il existe des situations où un tel accès de l'octet de fin permet d'éviter une partie de la manutention des cas spéciaux, ainsi, de réduire la complexité du code. Donc, il est certainement une option à considérer, de pesage de la laideur de l' c_str() appel contre le code supplémentaire de la complexité explicitement la manipulation des chaînes vides.


Btw, c'est probablement aussi la raison pour laquelle vous l'avez remarqué que votre code ne plante pas: Votre std::string mise en œuvre pour soutenir l' c_str() de la fonction, et de la façon la plus simple de le faire est d'utiliser un zéro chaîne terminée dans le stockage interne (plus fin pointeur ou le nombre de caractères pour permettre à zéro octets à l'intérieur de cette chaîne). De cette façon, les deux fonctions begin() et c_str() renvoient un pointeur vers la mémoire interne.

Encore, ce n'est rien que vous pouvez compter sur, parce que la norme ne garantit pas que le comportement en aucune façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X