Je vois trois problèmes principaux dans votre code :
-
Utilisation de pointeurs nus et propriétaires.
-
Utilisation du nu new
.
-
Utilisation de tableaux dynamiques.
Chacun est indésirable pour ses propres raisons. Je vais essayer d'expliquer chacune d'elles à tour de rôle.
(1) viole ce que j'aime appeler exactitude de la sous-expression et (2) viole exactitude de l'énoncé . L'idée ici est qu'aucune déclaration, et même pas toute sous-expression devrait être une erreur en soi. Je prends le terme "erreur" au sens large pour signifier "pourrait être un bug".
L'idée d'écrire un bon code est que si ça se passe mal, ce n'est pas de votre faute. Votre état d'esprit de base devrait être celui d'un lâche paranoïaque. Ne pas écrire de code du tout est une façon d'y parvenir, mais comme cela répond rarement aux exigences, la meilleure chose à faire est de s'assurer que quoi que vous fassiez, ce n'est pas de votre faute. La seule façon de prouver systématiquement que ce n'est pas votre faute est qu'aucun code n'a été écrit. partie de votre code est la cause première d'une erreur. Maintenant, regardons à nouveau le code :
-
new std::string[25]
est une erreur, car elle crée un objet alloué dynamiquement qui est fui. Ce code ne peut que conditionnellement devenir une non-erreur si quelqu'un d'autre, quelque part ailleurs, et dans tous les cas, se souvient de nettoyer.
Cela nécessite, tout d'abord, que la valeur de cette expression soit stockée quelque part. Cela se produit dans votre cas, mais dans des expressions plus complexes, il peut être difficile de prouver que cela se produira dans tous les cas (ordre d'évaluation non spécifié, je vous regarde).
-
foo = new std::string[125];
est une erreur parce qu'une fois de plus foo
fuit une ressource, sauf si les étoiles s'alignent et quelqu'un se souvient, dans tous les cas et au bon moment, de faire le ménage.
La façon correcte d'écrire ce code jusqu'à présent serait :
std::unique_ptr<std::string[]> foo(std::make_unique<std::string[]>(25));
Notez que chaque sous-expression dans cette déclaration n'est pas la cause profonde d'un bug du programme. Ce n'est pas votre faute.
Enfin, en ce qui concerne le point (3), les tableaux dynamiques sont un défaut du C++ et ne devraient en principe jamais être utilisés. Il existe plusieurs défauts standard concernant uniquement les tableaux dynamiques (et qui ne sont pas considérés comme valant la peine d'être corrigés). L'argument simple est que vous ne pouvez pas utiliser les tableaux sans connaître leur taille. Vous pourriez dire que vous pourriez utiliser une valeur sentinelle ou une valeur de pierre tombale pour marquer la fin d'un tableau de façon dynamique, mais cela rendrait la correction de votre programme plus difficile. valor -dépendante, non type -et donc non vérifiable statiquement (la définition même de "unsafe"). Vous ne pouvez pas affirmer statiquement que Ce n'était pas votre faute.
Vous finissez donc par devoir maintenir un stockage séparé pour la taille du tableau de toute façon. Et devinez quoi, votre implémentation doit de toute façon dupliquer cette connaissance afin de pouvoir appeler les destructeurs lorsque vous dites delete[]
donc c'est une duplication inutile. La bonne méthode, au contraire, est de ne pas utiliser de tableaux dynamiques, mais de séparer l'allocation de mémoire (et de la rendre personnalisable via des allocateurs, tant que nous y sommes) de la construction d'objets par éléments. Envelopper tout cela (allocateur, stockage, nombre d'éléments) dans une classe unique et pratique est la méthode C++.
Ainsi, la version finale de votre code est la suivante :
std::vector<std::string> foo(25);