L'initialisation de std::vector de std::string
Tout en travaillant dans un projet avec un code existant, j'ai trouvé cette fonction:
std::vector<std::string> Object::getTypes(){
static std::string types [] = {"type1","type2", "type3"};
return std::vector<std::string> (types , types +2);
}
J'aurais probablement écrit ceci:
std::vector<std::string> Object::getTypes(){
std::vector<std::string> types;
types.push_back("type1");
types.push_back("type2");
types.push_back("type3");
return types;
}
Est-ce qu'un choix de style ou est-il quelque chose que je suis absent? Toute aide serait grandement appréciée. Désolé si c'est trop basique.
Mise à jour:
En fait trouvé les différentes classes qui remplacent la même méthode de le faire d'une façon ou l'autre, donc C'est encore plus ambiguë. Je ferait tout de même, mais préférez la meilleure approche, si il y en a un.
Modifier
Veuillez noter que l'héritage de code est incorrect, car il initialise le vecteur avec seulement les deux premiers éléments de la matrice. Cependant, cette erreur a été discuté dans les commentaires, et devrait donc être préservée.
L'initialisation correcte aurait dû se lire comme suit:
...
return std::vector<std::string> (types, types + 3);
...
return std::vector<std::string>{"type1","type2", "type3"};
.Aussi, dans cette version, l'isolement de code et de données est de plus en plus apparente, il est donc syntaxiquement plus propre.
Correction à mon commentaire précédent: en C++11, vous pouvez l'atteindre en moins de mots:
return {"type1","type2", "type3"};
.La première version est la plus sujette à erreur, comme l'a démontré par le tout-en-un erreur ici.
Pas si vous utilisez
std::begin
et std::end
(ce qui devrait, bien sûr).OriginalL'auteur Andres Bucci | 2013-12-17
Vous devez vous connecter pour publier un commentaire.
Le tableau
types
dans le premier exemple est déclarée statique. Cela signifie qu'il existe seulement une fois en mémoire. Donc, il y a trois options pour ce retour et ils vivent dans la mémoire statique. Ensuite, lorsque vous créez le vecteur de retour, vous êtes en mesure d'allouer de la mémoire d'un seul coup en passant le début et la fin du tableau, comme les itérateurs.En le faisant de cette façon, vous n'avez pas les appels successifs à
push_back
ce qui signifie que le vecteur de ne pas avoir à réaffecter interne de bloc de mémoire.Aussi, lorsque le vecteur est construit dans le cadre de l'appel de retour, les anciens compilateurs ont un temps plus facile de faire valeur de retour d'optimisation.
OriginalL'auteur Anthony
Si vous avez un C++11 est capable de compilateur et de la bibliothèque, de retour d'un initialiseur liste devrait être suffisant:
OriginalL'auteur Some programmer dude
Le code que vous avez trouvé est plus efficace (parce que
types[]
n'est attribuée une fois etpush_back
peut/va provoquer des ré-allocations). La différence est marginale, et à moins que vous appelezgetTypes
dans un (relativement grande) boucle il ne devrait pas du tout (et probablement il ne sera pas beaucoup d'importance, même lorsque vous ne l'appelez dans une grande boucle).En tant que tel, à moins qu'il crée un béton problème de performance, c'est un choix de style.
OriginalL'auteur utnapistim
En gros, c'est un choix de style. Je le ferais probablement quelque chose de plus comme
qui vous permet de modifier le nombre de choses dans les types, sans avoir à se rappeler de mettre à jour le nombre dans la ligne suivante.
vous devez
std::vector<std::string> (types , types + sizeof(types)/sizeof(std::string));
voir les modifications, les juanchopanza commentaire de battre mon montage par un peu. En gros, vecteur de ne pas avoir un (Tapez*, nelements) constructeur, il a un (itérateur, iterator) constructeur.
Je voulais sélectionner votre réponse que l'on a accepté, mais depuis celui que j'ai sélectionné contient une explication je pense que ça va être mieux pour les futurs lecteurs.
Quel est le problème avec l'aide de
std::being( types ), std::end( types )
que l'argument du constructeur du vecteur? (Si vous n'avez pas de C++11, bien sûr, vous utilisez les fonctions correspondantes dans votre boîte à outils.)OriginalL'auteur Michael Kohne
Une raison pour laquelle j'aime utiliser ce style d'initialisation avec les itérateurs (et C++11 de l'uniforme de l'initialisation et l'initialiseur de listes) est qu'il permet de séparer les données de code.
Répéter
push_back
un grand nombre de fois, il se sent mal parce que j'ai désespérément besoin de refactoriser. Aussi, lorsque vous en avez vraiment besoin juste pour initialiser le conteneur de données, alors vous voulez voir une liste de données, et pas vraiment de code qui génère des données. La méthode que vous avez trouvé dans la version originale correspond à ce principe mieux.OriginalL'auteur