Manière correcte de boucle à travers les tableaux c++
Récemment, j'ai trouvé beaucoup d'exemples, la plupart d'entre eux ce qui concerne le C++ 98, de toute façon j'ai créé mon simple-tableau et une boucle (codepad):
#include <iostream>
using namespace std;
int main ()
{
string texts[] = {"Apple", "Banana", "Orange"};
for( unsigned int a = 0; a < sizeof(texts); a = a + 1 )
{
cout << "value of a: " << texts[a] << endl;
}
return 0;
}
Sortie:
value of a: Apple value of a: Banana value of a: Orange Segmentation fault
Cela fonctionne bien, sauf le défaut de segmentation à la fin.
Ma question Est, est-ce que ce tableau / boucle est fait un bon moyen? J'utilise C++ 11 donc je voudrais être sûr qu'il correspond aux normes et ne pourrait pas être fait d'une meilleure façon?
6 réponses
En C / C++ sizeof
. donne toujours le nombre d'octets dans l'objet entier, et les tableaux sont traités comme un seul objet. Remarque: sizeof
un pointeur vers le premier élément d'un tableau ou d'un objet simple, donne la taille de l' pointeur, pas de l'objet(s) souligné. De toute façon, sizeof
ne pas donne le nombre d'éléments dans le tableau (sa longueur). Pour obtenir la longueur, vous devez diviser par la taille de chaque élément. par exemple.,
for( unsigned int a = 0; a < sizeof(texts)/sizeof(texts[0]); a = a + 1 )
Quant à le faire de la manière c++11, la meilleure façon de le faire c'est probablement
for(const string &text : texts)
cout << "value of text: " << text << endl;
Cela permet au compilateur de déterminer le nombre d'itérations dont vous avez besoin.
EDIT: comme d'autres l'ont souligné, std::array
est préféré en C++11 sur les tableaux bruts; cependant, aucune des autres réponses n'a abordé pourquoi sizeof
échoue tel quel, donc je pense toujours que c'est la meilleure réponse.
string texts[] = {"Apple", "Banana", "Orange"};
for( unsigned int a = 0; a < sizeof(texts); a = a + 1 )
{
cout << "value of a: " << texts[a] << endl;
}
Non. Totalement une mauvaise façon d'itérer à travers un tableau. sizeof(texts)
n'est pas égal au nombre d'éléments dans le tableau!
Le moderne, C++11 façons serait de:
- utiliser
std::array
si vous voulez un tableau dont la taille est connue à la compilation; ou - utiliser
std::vector
si sa taille dépend de l'exécution
Ensuite, utilisez range-for lors de l'itération.
#include <iostream>
#include <array>
int main() {
std::array<std::string, 3> texts = {"Apple", "Banana", "Orange"};
// ^ An array of 3 elements with the type std::string
for(const auto& text : texts) { // Range-for!
std::cout << text << std::endl;
}
}
Vous pouvez demander, comment est std::array
meilleur que le tableau ol' C? Le la réponse est qu'il a la sécurité et les caractéristiques supplémentaires d'autres conteneurs de bibliothèque standard, ressemblant principalement à std::vector
. En outre, la réponse est qu'il n'a pas les bizarreries de se décomposer en pointeurs et de perdre ainsi des informations de type, qui, une fois que vous perdez le type de tableau d'origine, vous ne pouvez pas utiliser range-for ou std::begin/end
dessus.
sizeof
vous indique la taille de la chose, et non pas le nombre d'éléments. Une façon plus C++11 de faire ce que vous faites serait:
#include <array>
#include <string>
#include <iostream>
int main()
{
std::array<std::string, 3> texts { "Apple", "Banana", "Orange" };
for (auto& text : texts) {
std::cout << text << '\n';
}
return 0;
}
Démo Ideone: http://ideone.com/6xmSrn
sizeof(texts)
sur mon système évalué à 96: le nombre d'octets requis pour le tableau et ses instances de chaîne.
Comme mentionné ailleurs, l' sizeof(texts)/sizeof(texts[0])
donnerait la valeur de 3 que vous attendiez.
Si vous avez une très courte liste des éléments que vous souhaitez gérer, vous pouvez utiliser le std::initializer_list introduit dans C++11 avec auto:
#include <iostream>
int main(int, char*[])
{
for(const auto& ext : { ".slice", ".socket", ".service", ".target" })
std::cout << "Handling *" << ext << " systemd files" << std::endl;
return 0;
}
Ajoute une valeur d'arrêt au tableau:
#include <iostream>
using namespace std;
int main ()
{
string texts[] = {"Apple", "Banana", "Orange", ""};
for( unsigned int a = 0; texts[a].length(); a = a + 1 )
{
cout << "value of a: " << texts[a] << endl;
}
return 0;
}