OVH Cloud OVH Cloud

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
Julien Lamy
Julien Lamy wrote:


std::vector<int> n;

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



*i = 0;

}

std::vector<int> n;

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



n[i]=0;

}


Que choisir ?


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 ?


Tout : on ne peut pas accéder au n-ème élément d'une liste l par l[n].
Même si on pouvait, la complexité serait probablement linéaire en n,
donc à éviter. Même chose pour d'autres conteneurs qui ne définissent
pas operator[] pour accéder aux éléments.


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 ?


Outre le risque qu'évoque Olivier Azeau dans un autre post, il y a mieux
dans ce cas précis : soit le constructeur de vecteur, soit l'algorithme
fill :
// 10 elements initialises a 42
std::vector<int> v1(10, 42);
// 10 elements, remplis a 42
std::vector<int> n1(10);
std::fill(v.begin(), v.end(), 42);



Avatar
AG
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.

Avatar
Jean-Marc Bourguet
AG writes:

Jean-Marc Bourguet wrote:

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?


non, mais par contre, dans toutes les classes, les notes vont de 0 à 20.


Il te faudrait donc 21 entiers :-)

--
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
korchkidu
Fabien LE LEZ wrote:
On Wed, 09 Feb 2005 11:11:22 +0100, AG :



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


Pour quelles raisons precisement?

K.

Avatar
AG
Jean-Marc Bourguet wrote:

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?


non, mais par contre, dans toutes les classes, les notes vont de 0 à 20.



Avatar
AG
Fabien LE LEZ wrote:

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++.



ok.



Avatar
Julien Lamy
Fabien LE LEZ wrote:

On Wed, 09 Feb 2005 11:11:22 +0100, AG :



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



Pour quelles raisons precisement?


Pour éviter des copies en trop : le code de l'operator ++ postfixé est
en général quelque chose du genre :

T ancien(*this);
++(*this);
return ancien;


Avatar
AG
Jean-Marc Bourguet wrote:

Il te faudrait donc 21 entiers :-)


:-)

Avatar
Fabien LE LEZ
On 09 Feb 2005 11:25:35 +0100, Jean-Marc Bourguet :

non, mais par contre, dans toutes les classes, les notes vont de 0 à 20.


Il te faudrait donc 21 entiers :-)


Depuis quand les demi-points sont interdits ?

--
;-)


Avatar
kanze
AG wrote:
Julien Lamy wrote:


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 ?


Le convertir en boucle du premier type. Il n'y a pas de fonction
d'indexation dans std::list.

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,


Si tu veux faire exactement ça, tu écris simplement :

std::fill( n1.begin(), n1.end(), 0 ) ;
std::fill( n2.begin(), n2.end(), 1 ) ;

Il existe bien des cas où tu dois accéder dans plusieurs
collections « en parallel ». Les solutions varient selon
l'application et ce qu'on fait, mais l'utilisation d'UNE indice
est certainement une option à considérer. Mais pas forcément la
seule.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



1 2 3 4 5