Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

boucle for sur std::vector [debutant]

48 réponses
Avatar
AG
Bonjour,

je débute avec l'utiliation des vecteurs de la stl, et je me demandais
comment écrire une boucle for. J'ai vu dans les news une méthode assez
courante :



std::vector<int> n;

for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)
{
}

Je trouve cette méthode lourde à écrire. Plus simplement j'aurais vu
(entre autre) :

std::vector<int> n;

for(int i=0;i<n.size();i++)
{
}


Que choisir ? Si je n'ai pas besoin de l'iterator dans la boucle, la
seconde solution est-elle meilleure (plus lisible, plus simple, plus
rapide ? )

AG.

10 réponses

1 2 3 4 5
Avatar
Nicolas
AG wrote:
Bonjour,

je débute avec l'utiliation des vecteurs de la stl, et je me demandais
comment écrire une boucle for. J'ai vu dans les news une méthode assez
courante :



std::vector<int> n;

for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)
{
}

Je trouve cette méthode lourde à écrire. Plus simplement j'aurais vu
(entre autre) :

std::vector<int> n;

for(int i=0;i<n.size();i++)
{
}


Que choisir ? Si je n'ai pas besoin de l'iterator dans la boucle, la
seconde solution est-elle meilleure (plus lisible, plus simple, plus
rapide ? )


Les itérateurs te permettent de t'abstraire du type de données en
général. La solution avec un indexage en entiers (et accès par v.at(i)
sans doute) est valable dans ce cas. Mais il sera utile pour toi de
connaitre les itérateurs si tu veux pouvoir utiliser d'autres
conteneurs. Par exemple map<string, int>, qui contient des paires (type
pair<string, int>) de données. Pour le parcourir, tu vas utiliser un
itérateur :
for(std::map<string, int>::iterator i= m.begin(); i != m.end(); i++){
std::cout << "A la position " << (*i).first << " l'entier est " <<
(*i).second << "std::endl;
}


Cela te permet d'avoir une interface générique pour tes conteneurs, et
de toujours savoir comment les parcourir : prendre un iterator, partir
de begin() et s'arrêter avant end() en faisant des i++.

Pour ce qui est de la rapidité, je ne sais pas. Cela dépend sans doute
du compilateur, de l'implémentation, et du conteneur.
AG.


Nicolas.

Avatar
Matthieu Moy
Nicolas writes:

Pour ce qui est de la rapidité, je ne sais pas. Cela dépend sans doute
du compilateur, de l'implémentation, et du conteneur.


Sans optimisation, a priori, la solution avec itérateur est plus
rapide (ça va plus vite de calculer *i que v[j] qui revient a
*(v+j) ).

En pratique, il y a fort a parier qu'un compilateur digne de ce nom
génère le même code dans les deux cas.

--
Matthieu

Avatar
Julien Lamy
Bonjour,

je débute avec l'utiliation des vecteurs de la stl, et je me demandais
comment écrire une boucle for. J'ai vu dans les news une méthode assez
courante :



std::vector<int> n;

for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)
{
}

Je trouve cette méthode lourde à écrire. Plus simplement j'aurais vu
(entre autre) :

std::vector<int> n;

for(int i=0;i<n.size();i++)
{
}


Que choisir ?


Je suppose que tu veux accéder aux éléments du vecteur dans ta boucle,
donc avec un *i dans la premiere version et un n[i] dans la seconde.

La première solution est plus indépendante du conteneur : si tu changes
ton vecteur par une liste, tu auras juste à changer le type de
l'itérateur dans ta boucle for, et le code du parcours reste le même.

La seconde solution est effectivement plus lisible *si* tu n'as pas
l'habitude des itérateurs.

Au niveau performances, tu devrais obtenir quasiment la même chose,
surtout si le traitement dans la boucle est un peu complexe.

Si je n'ai pas besoin de l'iterator dans la boucle, la
seconde solution est-elle meilleure (plus lisible, plus simple, plus
rapide ? )


Si tu n'as pas besoin de l'itérateur dans la boucle, tu ne modifies pas
ton vecteur, et j'ai alors du mal à voir l'intérêt de cette boucle :-)

--
Julien

Avatar
Olivier Azeau
AG wrote:
maintenant je veux faire :

std::vector<int> n1(10);
std::vector<int> n2(10);

for(int i=0;i<n1.size();i++)
{
n1[i]=0;
n2[i]=1;
}


La, tu prends quand meme le risque que n2 et n1 ne soient pas de la
meme taille. Et s'ils l'étaient quelle raison peut-on alors avoir pour
faire 2 vecteurs distincts ?

Avatar
AG
Julien Lamy wrote:


Bonjour,

je débute avec l'utiliation des vecteurs de la stl, et je me demandais
comment écrire une boucle for. J'ai vu dans les news une méthode assez
courante :



std::vector<int> n;

for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)
{
*i = 0;


}

Je trouve cette méthode lourde à écrire. Plus simplement j'aurais vu
(entre autre) :

std::vector<int> n;

for(int i=0;i<n.size();i++)
{
n[i]=0;


}


Que choisir ?



Je suppose que tu veux accéder aux éléments du vecteur dans ta boucle,
donc avec un *i dans la premiere version et un n[i] dans la seconde.
oui



La première solution est plus indépendante du conteneur : si tu changes
ton vecteur par une liste, tu auras juste à changer le type de
l'itérateur dans ta boucle for, et le code du parcours reste le même.
que devrais-je changer dans la deuxième boucle si je passe d'un vecteur

à une liste ?


La seconde solution est effectivement plus lisible *si* tu n'as pas
l'habitude des itérateurs.

Au niveau performances, tu devrais obtenir quasiment la même chose,
surtout si le traitement dans la boucle est un peu complexe.

Si je n'ai pas besoin de l'iterator dans la boucle, la
seconde solution est-elle meilleure (plus lisible, plus simple, plus
rapide ? )


Si tu n'as pas besoin de l'itérateur dans la boucle, tu ne modifies pas
ton vecteur, et j'ai alors du mal à voir l'intérêt de cette boucle :-)


certes, mais tu m'avais compris...


maintenant je veux faire :

std::vector<int> n1(10);
std::vector<int> n2(10);

for(int i=0;i<n1.size();i++)
{
n1[i]=0;
n2[i]=1;
}

si je veux faire cela avec des iterateurs, suis-je obligé de faire :

std::vector<int> n1(10);
std::vector<int> n2(10);

std::vector<int>::iterator i1;
std::vector<int>::iterator i2;

for(i1=n1.begin(),i2=n2.begin();i1!=n1.end();i1++,i2++)
{
*i1=0;
*i2=1;
}


c'est à dire utiliser deux iterator ?


Avatar
Fabien LE LEZ
On Wed, 09 Feb 2005 10:03:51 +0100, AG :

for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)


C'est effectivement presque la méthode habituelle pour les boucles for
classiques.
En fait, il y a deux écritures :

for (std::vector<int>::iterator i=n.begin(); i!=n.end(); ++i)
si tu veux modifier le contenu du tableau

for (std::vector<int>::const_iterator i=n.begin(); i!=n.end(); ++i)
si tu ne veux pas modifier le contenu du tableau

(note le ++i au lieu de i++)

Mais bien souvent, on essaie d'écrire

for_each (n.begin(), n.end(), Predicat);

où "Predicat" est le prédicat qui va bien.


--
;-)

Avatar
Falk Tannhäuser
AG wrote:

maintenant je veux faire :

std::vector<int> n1(10);
std::vector<int> n2(10);

for(int i=0;i<n1.size();i++)
{
n1[i]=0;
n2[i]=1;
}


Là, tu peux faire
std::fill(n1.begin(), n1.end(), 0);
std::fill(n2.begin(), n2.end(), 1);
(ne pas oublier '#include <algorithm>' avant). On peut souvent
se passer des boucles 'for' en utilisant les algorithmes standard.

Sinon il est possible de remplir les vecteurs avec la valeur
souhaitée dès la construction :

std::vector<int> n1(10, 0); // équivalent à :
//std::vector<int> n1(10);

std::vector<int> n2(10, 1);

Falk

Avatar
Fabien LE LEZ
On Wed, 09 Feb 2005 11:11:22 +0100, AG :

Permet moi, en tant que débutant, de repousser ce genre de détails à
plus tard,


Bof... Je te conseille d'écrire systématiquement ++i, et de remettre à
plus tard l'idée qu'on peut écrire i++.



--
;-)

Avatar
Jean-Marc Bourguet
AG writes:

Olivier Azeau wrote:

La, tu prends quand meme le risque que n2 et n1 ne soient pas de la
meme taille. Et s'ils l'étaient quelle raison peut-on alors avoir pour
faire 2 vecteurs distincts ?


Les exemples de ce type sont légions. imagine deux vecteurs de 20 entiers
représentants les distributions de notes pour deux classes d'élèves
différentes.


Les classes sont contraintes a avoir le meme nombre d'eleves de nos
jours?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
AG
Fabien LE LEZ wrote:

On Wed, 09 Feb 2005 10:03:51 +0100, AG :


for(std::vector<int>::iterator i=n.begin();i!=n.end();i++)



C'est effectivement presque la méthode habituelle pour les boucles for
classiques.
En fait, il y a deux écritures :

for (std::vector<int>::iterator i=n.begin(); i!=n.end(); ++i)
si tu veux modifier le contenu du tableau

for (std::vector<int>::const_iterator i=n.begin(); i!=n.end(); ++i)
si tu ne veux pas modifier le contenu du tableau

(note le ++i au lieu de i++)
Permet moi, en tant que débutant, de repousser ce genre de détails à

plus tard, peut être dans une deuxième phase d'optimisation ? (mais
j'avais bien noté).


Mais bien souvent, on essaie d'écrire

for_each (n.begin(), n.end(), Predicat);

où "Predicat" est le prédicat qui va bien.
Ah ok. Je note cette troisième manière. je vais voir si ça rentre dans

mes "Prédicats".


1 2 3 4 5