Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Faut-il bannir les boucles "for" du C++
Au profit des algorithmes de la bibliothèque standard ?

Le , par gbdivers

0PARTAGES

8  0 
Utilisez-vous les algorithmes de la STL en 2012 ?
La boucle for face aux algorithmes de la bibliothèque standard

J'ai donné un jour un exercice à l'un de mes stagiaires : modifier tout le code d'un projet qu'il avait écrit pour remplacer toutes les boucles for par des algorithmes de la bibliothèque standard.

Au-delà de ma simple tendance naturelle à torturer les stagiaires, je trouvais cet exercice intéressant pour plusieurs raisons.
La première est pédagogique, pour habituer mon stagiaire à apprendre et à utiliser les outils existants de la bibliothèque standard plutôt que repartir systématiquement de zéro.
La seconde raison est une question d'expressivité. Lorsque l'on rencontre un for dans le code, on ne peut pas savoir ce que va faire ce code. Il est nécessaire de lire le contenu du bloc et cela peut devenir très complexe, surtout si on appelle beaucoup de fonctions et que l'on manipule de nombreux objets dans ce bloc.
La dernière raison est plus conceptuelle. Lorsque l'on conçoit son algorithme en terme de boucle for, on réfléchit en fait en terme d'implémentation. Penser en termes d'algorithmes de la bibliothèque standard, c'est penser en termes de concepts que l'on manipule. On obtiendra alors plus facilement du code propre, maintenable et évolutif.

Que pensez-vous de cette attitude de supprimer, sauf choix conscient et justifié, les boucles for du code au profit de la STL ?
Voyez-vous d'autres justifications ou contre-arguments pour l'utilisation systématique des algorithmes de la STL ?
D'un point de vue pédagogique, que pensez-vous de cet exercice ?
Dans un cadre professionnel, pensez-vous que cette règle soit utile ? Applicable ?
Avez-vous des exemples de code utilisant des boucles for qui ne pourraient pas être réécrits avec les algorithmes de la STL ?

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de JolyLoic
Rédacteur/Modérateur https://www.developpez.com
Le 05/04/2012 à 2:41
Puisque je suis la personne citée, je vais répondre, même si ce n'est pas moi qui ait ouvert cette discussion et que j'ai l'impression qu'une partie des reproches lui est adressée.
Citation Envoyé par singman  Voir le message
Alors là, je pense qu'on touche le fond...
Déjà l'idée d'interdire le for() est stupide (oui, stupide mais je pense encore plus).

Encore une fois, l'idée n'a jamais pour moi été d'interdire, mais de déconseiller, et a contrario de conseiller les alternatives.
Citation Envoyé par singman  Voir le message
Mais vouloir faire croire qu'utiliser la STL rend le code plus expressif !

Je le dis et le maintiens. Et je vais donner quelques exemples, avec des algorithmes simples (c'est à dire qu'avec des algorithmes plus complexes, l'intérêt est encore plus grand).
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void fctFor1(vector const ¬es) 
{ 
	int nombreElèvesPassant = 0; 
	for (size_t i = 0 ; i= 10) 
		{ 
			nombreElèvesPassant++; 
		} 
	} 
	cout << "Elèves passant : " << nombreElèvesPassant << endl; 
} 
 
void fctStl1(vector const ¬es) 
{ 
	int nombreElèvesPassant = count_if(notes.begin(), notes.end(), [](double d){return d>=10;}); 
	cout << "Elèves passant : " << nombreElèvesPassant << endl; 
}
Ici, j'ai hésité à supprimer la variable intermédiaire. Dans du vrai code, elle disparaîtrait probablement. Le code STL permet immédiatement de savoir que l'on va compter. En plus, on veut une valeur, on appelle une fonction, c'est direct. J'aurais aimé pouvoir le simplifier en count_if(notes, [](d){return d>=10;});, mais le C++ ne permet pas encore ça.
Le code à base de for ne s'écrit plus comme une fonction, mais comme un bout de code modifiant une variable locale. On remplace une fonction pure par du code statefull, ce qui est généralement moins clair.

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void fctFor2(vector notes) 
{ 
	display(notes); 
	for (size_t i = 0 ; i notes) 
{ 
	display(notes); 
	replace_if(notes.begin(), notes.end(), [](double d){return d<0;}, 0); 
	display(notes); 
}
Mêmes principe. Dans du vrai code, j'écrirais probablement un commentaire avant le for, je n'en verrai pas l'utilisé avant le replace_if : il ne ferait que paraphraser le code.
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void fctFor3(vector const ¬es) 
{ 
	for (size_t i = 0 ; i const ¬es) 
{ 
	if (all_of(notes.begin(), notes.end() , [](double d){return d>=10;})) 
	{ 
		cout << "J'ai une classe de génies" << endl; 
	} 
	else 
	{ 
		cout << "Je n'ai pas une classe de génies" << endl; 
	} 
}
Citation Envoyé par singman  Voir le message
Non mais je dois rêver, vous avez apprit le C comment ?

Je n'ai jamais vraiment appris le C, mais je ne vois pas le rapport.
Citation Envoyé par singman  Voir le message
La compréhension de ce que fait un code n'est JAMAIS dans le code lui même, quelque soit le langage, mais dans la manière dont il est écrit.
Il faut commenter, expliquer, éviter les astuces personnelles, se conformer au standard de l'entreprise pour laquelle on développe.

Je ne suis pas entièrement d'accord avec la première partie de la phrase. Par exemple les commentaires décrivent non pas ce que fait le code, mais ce que la personne l'ayant écrit croyait qu'il faisait. Quand il s'agit d'utiliser du code, les commentaires suffisent généralement. Quand il s'agit de le déboguer ou de le faire évoluer, ils ne sont plus suffisants, et un code écrit clairement devient alors un atout majeur.

Mais surtout pour moi les commentaires les plus intéressants sont ceux qui sont donnés non pas par // ou /* */ mais par des noms de variables ou de fonctions expressifs. Et on rejoint un des deux reproches que je fais à for : Il est tellement générique qu'il n'aide pas à comprendre dans quel objectif une boucle a été écrite (le deuxième étant qu'il est tellement générique qu'il est facile de se planter dans son utilisation). On peut certes mettre un commentaire avant le for, mais ça revient pour moi à utiliser des variables nommées v1, v2, v3 et à commenter à côté de la déclaration que v1 est le prix unitaire, v2 la quantité et v3 l'âge du vendeur.

Citation Envoyé par singman  Voir le message
Ce sondage est simplement un non-sense. Et vous êtes prof ?

Je suis avant tout développeur. Je donne un enseignement mais ce n'est pas mon activité principale. Par contre, j'ai pu constater grâce à ça qu'avant que l'entraînement et l'habitude ne viennent contrecarrer ça, les débutants se trompent régulièrement dans l'écriture d'une boucle for. Ce qui est en soi signe que c'est un des éléments complexes du langage, et donc une source de bugs, même dans du vrai code.
10  0 
Avatar de JolyLoic
Rédacteur/Modérateur https://www.developpez.com
Le 31/03/2012 à 23:45
J'aurais envie de répondre au sondage : Le plus souvent possible, mais pas plus ! Or le problème que j'ai est que si je me place en C++98, les alternatives aux boucles explicites me semblent encore bien pire.

Je crois que le seul algorithme qui de par la complexité de la boucle équivalente justifie que je l'utilise au lieu d'une boucle manuelle est le remove_if. Mais par exemple, for_each, j'ai essayé, et je suis revenu en arrière.

Maintenant, dans l'hypothèse C++11, la situation a changé. En bien.

Les lambdas rendent enfin les algorithmes de la STL utilisables. D'un autre côté, le range for loop présente quand il s'agit du cas très courant d'itérer sur un conteneur une syntaxe encore plus simple, plus directe et plus agréable que l'algorithme équivalent. Et même pour les boucles for classique, auto allège agréablement l'écriture.

Donc, en C++11, j'utiliserais par ordre de préférence :
- Le range for loop
- Un algorithme de la STL existant
- Une boucle for manuelle, que j'encapsulerait éventuellement dans un algorithme

Autant on peut dire que la programmation structuré a ouvert la guerre anti goto, que la programmation objet lutte farouchement contre if et switch, autant je ne pense pas que l'on soit arrivé au point où la boucle for soit à considérer comme à éviter, mais simplement on commence à avoir des alternative intéressantes pour les cas courants.

Certains langage vont plus loin que le C++ contre la boucle for, par exemple C# avec Linq, qui permet d'écrire du code qui travaille sur des données avec un philosophie proche du SQL (regroupement, tri, filtres...) sans expliciter les boucles nécessaires. Je n'ai pas encore réussi à me convaincre si au final je trouvais le résultat plus ou moins clair qu'avec les boucles explicites. Par contre, cette écriture ouvrait à des possibilités d'optimisation intéressantes.
9  0 
Avatar de Overcrash
Modérateur https://www.developpez.com
Le 31/03/2012 à 23:06
Bonsoir,

Bannir est un bien grand mot.

En C++ je pense que la différence entre un for et son équivalent en STL importe peu.
Je serais plus d'avis de laisser le développeur utiliser celui avec lequel il est plus à l'aise.

Par contre je suis curieux de voir qu'elle différence entre les deux, vitesse, monopolisation et co.
8  0 
Avatar de guigz2000
Membre actif https://www.developpez.com
Le 02/04/2012 à 13:04
Bannir le for du C++?
LOL....Plus serieusement,Non...

Plusieurs raisons:
1..Le for est une construction intrinseque au language.La STL en revanche est une librairie.Comme toute librairie elle peux etre changée et evoluer alors que le for classique ne changera pas. En plus sur certain compilateurs a la noix, la STL n'est pas toujours parfaitement supportée ou implementée.

2..J'aimerai bien voir un microbenchmark d'une boucle for et d'un equivalant STL.Je doute que au niveau performance cela soit vraiment similaire

3..Au niveau complexité, remplacer un élément de language par une librairie a tendance a me hérisser le poil,sauf si on attends une fonctionnalité bien spécifique et vraiment plus complexe.Cela aura tendance systematiquement a générer un microcode moins compact et plus lourd a l'execution.Meme si un compilateur optimise bien cela aura dans tous les cas une incidence sur la taille et la vitesse du code.Un algo reste un algo et il est souvent implementé lui meme avec des boucles for,while,etc...Il utilise des variables supplementaire, occupe de la memoire et contient troutes sortes de tests pas forcements necessaire pour l'utilisation voulue.En plus,un appel de fonction n'as jamais de consequences nulles au niveau performances.

4.. Pour ce qui est de la facilité de lecture, un commentaire expliquant une boucle for un peu complexe est souvent suffisant.

J'ai vraiment l'impression que dans la plupart des cas,utiliser la STL pour remplacer des constructions simples (dans ce cas une boucle for) reviens vraiment a utiliser un marteau pour tuer une mouche.Ca marche mais on prends le risque de se taper sur les doigts ou d'avoir une tendinite.
8  0 
Avatar de Klaim
Membre expert https://www.developpez.com
Le 02/04/2012 à 13:58
Citation Envoyé par unBonGars Voir le message

Mais un jour , il devront bien produire et pour cela sortir du schéma d'apprentissage pour rechercher un résultat. Admettons qu'ils restent en C++ au lieu de partir vers java C# etc... On écrit généralement du C++ dans un contexte commercial pour :
1. La vitesse d’exécution
2. L'accès au C et au bas niveau machine
3. Cross platform.
4. Certains languages sont interdit sur certaines plateformes, pas le C++.
5. Consommation mémoire réduite (voir Hip Hop pour les points 1 et 5)
6. Prédictabilité (temps-réél et semi-temps réél)
7. Non attaché à une société en particulier / standardisé
8. Nombre, variété & qualité des bibliothèques

etc.

Il y a bien plus que la vitesse d'execution et l'accès bas niveau comme raison de choisir cette catégorie de language.
7  0 
Avatar de Matthieu Brucher
Rédacteur https://www.developpez.com
Le 31/03/2012 à 23:05
Il y a souvent des boucles que j'implémenterai sous la forme de transform ou autres, mais ça me gonfle d'écrire :
- un foncteur, même si son nom sera bien précis et adapté
- une fonction lambda parce que mon IDE n'arrive pas à les parser correctement (merci Eclipse)

Maintenant, il m'arrive souvent aussi d'avoir à ajouter des compteurs à droite-gauche parce qu'un itérateur ne suffit pas, et dans ce cas, je ne sais pas trop comment utiliser un algorithme de la STL.

Bref, je sais qu'ils existent, mais je les utilise encore trop peu !
6  0 
Avatar de Obsidian
Modérateur https://www.developpez.com
Le 01/04/2012 à 1:45
Citation Envoyé par gbdivers Voir le message
La première est pédagogique, pour habituer mon stagiaire à apprendre et à utiliser les outils existants de la bibliothèque standard plutôt que repartir systématiquement de zéro. La seconde raison est une question d'expressivité. Lorsque l'on rencontre un for dans le code, on ne peut pas savoir que va faire ce code. Il est nécessaire de lire le contenu du bloc et cela peut devenir très complexe, surtout si on appelle beaucoup de fonctions et que l'on manipule de nombreux objets dans ce bloc.
Oui mais, en suivant ce raisonnement, il faudrait également retirer l'usage de while() et de do…while() qui ne sont pas très éloignées de for().

La dernière raison est plus conceptuelle. Lorsque l'on conçoit son algorithme en terme de boucle for, on réfléchit en fait en terme d'implémentation. Penser en termes d'algorithmes de la bibliothèque standard, c'est penser en termes de concepts que l'on manipule. On obtiendra alors plus facilement du code propre, maintenable et évolutif.
Tout le problème est là, à mon avis : ça part d'un bon sentiment mais ça introduit un effet pervers : sous prétexte d'inciter les gens à penser aux bons algorithmes, on risque en faite de leur désapprendre à y réfléchir eux-mêmes.

C'est un peu comme apprendre systématiquement et dès le départ à utiliser qsort(), en C, plutôt que de faire la moindre boucle pour trier ses éléments. Si ça se justifie en production (et que ça arrange bien tout le monde), les algorithmes de tri en eux-mêmes sont un passage incontournable dans toute formation supérieure en informatique.

C'est aussi faire l'hypothèse que les algos de la STL seront toujours plus adaptés et plus optimisé que ce que l'on pourra faire soi-même. C'est généralement vrai mais que ça ne peut l'être que jusqu'à un certain niveau. Or, si tout l'objet de l'approche consiste à utiliser au maximum des patterns tout faits en faisant abstraction de l'implémentation et du coût en ressources, alors je pense qu'il faut changer de langage. Et même, pourquoi pas, passer à un langage 100 % interprété, qui permet pour le coup de faciliter pas mal de facettes du paradigme objet, comme l'introspection.

Citation Envoyé par JolyLoic Voir le message
Autant on peut dire que la programmation structuré a ouvert la guerre anti goto, que la programmation objet lutte farouchement contre if et switch, autant je ne pense pas que l'on soit arrivé au point où la boucle for soit à considérer comme à éviter, mais simplement on commence à avoir des alternative intéressantes pour les cas courants.
Je ne l'aurais pas mieux dit. Je pense que l'approche de GBDivers est justifiée mais qu'elle ne doit justement n'être qu'une « méthode » donnée de conduite d'un projet, mais pas forcément une ligne à suivre de manière universelle.
6  0 
Avatar de
https://www.developpez.com
Le 03/04/2012 à 8:33
Citation Envoyé par air-dex  Voir le message
Excellent dans le cadre de l'apprentissage de la STL. Et puis c'est bon pour ce qui est de ne pas réinventer la roue.

Je ne vois pas très bien en quoi écrire :

Code : Sélectionner tout
for(int i=0;i
consiste davantage à réinventer la roue (ou est moins expressif que)

Code : Sélectionner tout
1
2
3
4
5
6
7
for_each(v.begin()v.end(),op); 
 
... (ailleurs dans le code, généralement loin) 
 
struct faire_qqch { 
   void operator()(int i) {fait_qqch(i);} 
} op;
On pourrait également débattre sur la vertu de "ne pas réinventer la roue". Neuf fois sur dix, ce "précepte" veut dire : utiliser LA librairie que JE connais (tu citais Qt...), et prétendre que LA première solution au problème que j'ai trouvée est la seule possible.

Mon expérience, c'est qu'en général, le code devient bon à la deuxième ou troisième itération. Imposer à des étudiants l'idée que "réinventer la roue" est un péché mortel me parait un peu dangereux. (Je suis bien évidemment d'accord que ce n'est pas une excuse pour ne pas connaitre la STL, ou récrire sa classe string...)

Pour que l'idée soit bonne, il faudrait que TOUS les développeurs C++ aient un très bon niveau en STL.

Pour bien utiliser la STL (ses algorithmes et ses conteneurs, tout au moins), il faudrait que les développeurs aient une bonne compréhension de l'algorithmique, et des garanties fournies par les différents conteneurs et algorithmes. On est loin du compte...

Francois
6  0 
Avatar de JolyLoic
Rédacteur/Modérateur https://www.developpez.com
Le 04/04/2012 à 19:00
Je pense en lisant certains commentaire que l'on n'a pas tous compris la question de la même manière. J'ai l'impression que certains ont lu :

Faut-il supprimer "for" du langage ?
A mon sens la réponse est non sans même hésiter. On a toujours goto, après tout

Pour ma part, j'ai lu :

Faut-il déconseiller l'usage de for (et implicitement while et do-while), c'est à dire le considérer comme la solution à utiliser en dernier, quand on s'est rendu compte que les autres ne marchent pas ?

Et là, mon avis est bien plus favorable. Je pense que si je pouvais écrire du code C++11 (et ne pas avoir à compiler avec des outils d'il y a 15 ans), mon code contiendrait très peu de boucle for écrites à la main (les range-based for loop, elles, seraient assez courantes).
6  0 
Avatar de
https://www.developpez.com
Le 02/04/2012 à 20:25
ben le bannir du langage non. C'est complètement utopique.

Je pense que la question soulevée, c'est qu'on se sert du for pour rien (et méconnaissance des alternatives) et que c'est synonyme de bad practice, jcrois que le sondage m'appuie, puisqu'il ne s'agit pas de voter un retrait des boucles for (un peu grossier comme exemple) mais plutot de savoir la fréquence d'utilisation des alternatives que chacun fait.

De toute façon, dès qu'on fait un peu de bas niveau, faut dire au revoir à la STL

Ca n'empêche pas de discuter sur les cas où il ne s'agit pas de performances mais de maintenance/lisibilité
5  0