Normes et conseils de programmation en C/C++
applicables en 1ère année dans le module "C++" et en 2ème
année dans les modules "systèmes d'exploitation" et "réseaux".
© D. Mathieu
mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique
Créé le 20/12/1999 - Dernière mise à jour : 13/01/2000

Sommaire
Organisation des fichiers
Structure d'un fichier
source
Structure
d'un fichier inclus .h - Directives d'inclusion conditionnelle
Imbrication de fichiers inclus
Présentation
Indentation
Commentaires
Aération
Listings
Identificateurs
Identificateurs
des variables et des fonctions
Identificateurs des classes
Identificateurs
des paramètres formels des constructeurs, des modifieurs, ou d'autres
fonctions membres de classes
Identificateurs des
espaces de noms
Identificateurs des
données membres
Identificateurs des constantes
Identificateurs
des prédicats ou variables booléennes
Accolades
Présentation
"K&R" (Kernighan and Richie)
Présentation "classique"
Terminaison
des classes, des fonctions, et des espaces de noms
Déclarations et définitions
Déclarations
et définitions des classes
Déclaration
et définition des namespace's
Déclaration
et définition des fonctions
Schéma alternatif
Rupture de séquence
Déséquilibre
des blocs "alors" et "sinon"
Simplification de la condition
L'opérateur ? :
Divers
Variables
intermédiaires - opérateurs spécifiques
Vérification des paramètres
Utilisation des constantes
Constante 0 ou NULL ?
Objets sur
la pile, objets en mémoire dynamique
Constructeurs
Test d'égalité
Affectation
Organisation des fichiers
Structure d'un fichier source
Afin de permettre une extraction automatique de documentation,
tout fichier source doit obligatoirement commencer par des commentaires
ayant rigoureusement le format suivant :
/**
*
* @File : tp_01.cxx
*
* @Authors : M. Laporte
*
D. Mathieu
*
* @Date : 28/12/99
*
* @Version : V1.0
*
* @Synopsis : Exemple d'entete de fichier
* qui
peut se continuer sur plusieurs lignes
*
* @SeeAlso : tp_02.cxx, cours C++
*
* @Bugs : indiquer les erreurs connues
* et non encore
corrigees
*
* @ToDo : indiquer ce qui reste a faire
*
* @Modified :
* @@Authors : M. Laporte
* @@Date : 27/12/99
* @@Synopsis : correction de la date de creation
...
*
* @Modified :
* @@Authors : D. Mathieu
* @@Date : 29/12/99
* @@Synopsis : correction de la correction
de M. Laporte ...
*
**/ |
Les parties en gras sont obligatoires. Les
parties en italiques sont à remplir par vous-même.
Sommaire
Structure
d'un fichier inclus .h - Directives d'inclusion conditionnelle
Tout fichier .h doit les contenir. Elles doivent
inclure la totalité du code du fichier (donc commencer immédiatement
après les commentaires de début de fichier). Elles doivent
utiliser une constante symbolique construite à partir du nom de
fichier en MAJUSCULES, précédé et suivi de deux '_'
(caractère souligné). Le '.' est également remplacé
par un '_'.
/**
*
* @File : nsSysteme.h
*
* @Authors : M. Laporte
*
D. Mathieu
*
* @Date : 28/12/99
*
* @Version : V1.0
*
* @Synopsis : espace de noms nsSysteme contenant les fonctions
systeme et ..
*
**/
#if !defined __NSSYSTEME_H__
#define __NSSYSTEME_H__
// totalite du code
#endif // __NSSYSTEME_H__ |
Sommaire
Imbrication de fichiers inclus
Lorsque, dans un fichier source f.h ou f.cxx,
une ligne de code utilise une déclaration contenue dans un fichier
xxx.h,
celui-ci doit obligatoirement être directement inclus. Considérons
l'exemple suivant :
-
Le fichier signal.h contient de nombreuses déclarations
parmi lesquelles la constante SIG_DFL et la fonction système
signal()
:
// fichier signal.h
// contient la déclaration de SIG_DFL
// contient la déclaration de la fonction signal() |
-
Le fichier trait.h contient la définition de la fonction
TraiterSignal(),
qui utilise la fonction système signal(), et nécessite
donc l'inclusion du fichier signal.h (en réalité,
le fichier csignal en C++) :
// fichier trait.h
#include <csignal> // signal()
namespace nsTrait
{
void TraiterSignal (...)
{
signal (...);
} // TraiterSignal()
// autres déclarations
} // nsTrait |
-
Supposons enfin que le fichier exo_01.cxx utilise d'une part la
constante SIG_DFL qui est définie dans le fichier csignal,
d'autre part la fonction Traitement(), déclarée
dans le fichier trait.h.
// fichier exo_01.cxx
// utilise la constante SIG_DFL ==>
#include <csignal> // SIG_DFL
// utilise la fonction TraitSignal()==>
#include "trait.h"
// suite des déclarations |
Dans le fichier exo_01.cxx, le fichier csignal
est inclus deux fois : directement et indirectement par l'intermédiaire
de trait.h. C'est la raison pour laquelle il est impératif
que chaque fichier inclus ait les directives
d'inclusion conditionnelles rappelées ci-dessus. Une autre solution
serait de ne pas inclure directement <csignal> dans exo_01.cxx,
sachant qu'il est inclus indirectement. L'expérience prouve que,
à terme, on ne sait plus où on en est, car il y a parfois
deux, trois ou même plus de niveaux d'imbrication des fichiers inclus
et la moindre modification devient catastrophique.
Sommaire
Présentation
Indentation
Elle doit être de 4 caractères :
void Fct (...)
{
int i;
{
// bloc interne
int j;
//...
}
} // Fct() |
Dans certains cas, on pourra utiliser une demi-indentation
de 2 caractères : case dans une instruction switch,
switch (cond)
{
case '1' :
...
break;
case '2' :
...
break;
} |
private , protected ou public dans une classe
:
class CX
{
private :
...
protected :
...
public :
...
}; |
Sommaire
Commentaires
Ce paragraphe ne concerne que les commentaires destinés
à la documentation interne au fichier (explications destinées
à faciliter la relecture et la compréhention du code).
Utilisez de préférence les commentaires
//.
Réservez les commentaires entre /* */ soit pour isoler
une partie de ligne :
void Fct (const int n, const int Structure /* = 0 */)
... |
ou une partie de programme (attention à ne pas les imbriquer)
:
/*
Plusieurs lignes,
par exemple des explications
en début de fichier
*/ |
ou
/*
Risque d'erreur, par exemple :
void Fct (const int n, const int Structure /*
= 0 */)
*/ |
Eviter si possible des commentaires en fin de ligne
de code, aligner les commentaires sur le code pour respecter l'indentation,
séparer les commentaires du code par une ligne vierge au-dessus
et au-dessous.
Limiter les commentaires :
-
à la présentation du contenu
du fichier, de chaque classe, de chaque fonction,
-
à la présentation générale des algorithmes,
-
à l'explication de code particulièrement difficile à
lire (souvent des conditions multiples, effets de bord souhaités,
etc...).
Pour le reste, essayer de choisir des
identificateurs les plus parlants.
Sommaire
Aération
Un listing doit pouvoir être parcouru en lecture
rapide, pour situer rapidement une partie recherchée. N'hésitez
pas à sauter une ligne de temps en temps pour séparer deux
"paragraphes". De même, mettez des espaces sur une ligne, pour encadrer
les opérateurs, après chaque virgule, avant une parenthèse
ouverte, après une parenthèse fermée sauf si elle
est suivie d'une ponctuation, etc ..., bref, suivez les règles habituellement
utilisée en typographie :
cettephraseestaussidifficilealirequecellequivasuivrecarchaquemotoutokenestcolléauxautres!!!
if((n=waitpid(process_id,status_location,option))==-1) |
qui est beaucoup moins agréable que :
if (-1 == (n = waitpid (ProcessID, StatusLocation, Option))) //
voir aussi Tests d'égalité |
Sommaire
Listings
Lorsque des listings doivent être rendus sur papier,
ils doivent être édités en utilisant une police de
caractères non proportionnelle (par exemple MS LineDraw
- attention : pas de caractères accentués - ou Courier
New). Evitez absolument les polices proportionnelles ou étroites.
Dans la mesure du possible, la définition
d'une fonction doit tenir sur une page. Si elle dépasse une page,
n'hésitez pas à mettre certaines parties sous forme de fonctions
(inline par exemple). N'imprimez pas une fonction à cheval
sur deux pages. Si c'est inévitable, choisissez l'endroit de la
coupure astucieusement (pas en plein milieu d'une structure alternative
par exemple).
Lorsque vous saisissez les programmes à l'écran,
pensez que les lignes longues risquent d'être coupées sur
l'imprimante, terminées au début de la ligne suivante, en
rompant ainsi l'indentation. Dès la saisie, ne dépassez pas
les colonnes 70 ou 75.
Sommaire
Identificateurs
Identificateurs
des variables et des fonctions
Le choix des identificateurs est une opération
primordiale pour la lisibilité: trop longs, ils ralentissent la
lecture, sont fastidieux et prennent trop de place sur une ligne; trop
courts, ils ne ressemblent plus qu'à des onomatopées impossibles
à prononcer et dénuées de sens. C'est le bon choix
d'un identificateur qui rend superflu un commentaire.
-
Eviter le plus possible l'utilisation du souligné '_',
-
Mettre en majuscule le premier caractère des "mots" qui composent
l'identificateur : préférer CopieFichier() à
copie_fichier().
Cette règle souffre quelques exceptions, comme par exemple :
-
les indices en mathématiques sont généralement notés
i, j, k, etc... Il est souhaitable de garder cette convention.
-
certains identificateurs très abrégés sont d'un usage
courant, comme par exemple is pour input stream,
fd
pour file descriptor. Il est alors exclu de mettre la première
lettre en majuscule, ce qui donnerait IS ou FD. Or seules
les macro-instructions (destinées au préprocesseur) doivent
être totalement en majuscules. Les avis sont partagés
pour des identidicateurs s pour string, c pour
character,
etc... qui peuvent être en minuscules ou en majuscules, ou remplacés
par Str et Car !
-
Utiliser des préfixes simples, comme par exemple Nb pour
NombreDe
(préférable à Cpt... pour Compteur),
Lg
pour LongueurDe, Num pour NumeroDe (à
préférer à No qui peut être confondu
avec la négation en anglais), etc... Les préfixes peuvent
eux-mêmes être combinés : MaxNbParam pour le NombreMaximalDeParametres
...
-
Ne pas avoir peur de mélanger le fraçais et l'anglais pour
faire plus court : préférer Size à Taille,
mais Pile à Stack
-
NbCarLus, NbVoyelles, NbLecteurs,
etc...
-
LgMot, LgLigne, etc...
-
NumErreur, NumLigne, etc...
-
MaxSize, MaxNbParam, etc...
-
Utiliser des identificateurs dont la prononciation n'est pas ambiguë
: préférer Car à Char, Fich
à Fic, éviter File (qui peut évoquer
une file ou un fichier en anglais !)
-
Certains préconisent d'utiliser toujours un verbe (en français
ou en anglais, pour faire plus court) pour désigner une fonction,
par exemple TraiterOperande(), ChercherImage(),
Tasser(),
etc... Voir aussi les prédicats.
Sommaire
Identificateurs des classes
Faire précéder le nom de la classe (qui
doit commencer par une majuscule) d'un C majuscule :
Sommaire
Identificateurs
des paramètres formels des constructeurs, des modifieurs, ou d'autres
fonctions membres de classes
Lorsque des paramètres formels de fonctions membres
servent à initialiser des données membres, utiliser le même
identificateur que celui de la donnée membre correspondante, sans
le m_ :
class CDate
{
unsigned m_An;
unsigned m_Mois;
unsigned m_Jour;
public :
CDate (const unsigned An,
const
unsigned Mois,
const
unsigned Jour);
void SetAn (const unsigned An);
//
}; // CDate |
Sommaire
Identificateurs
des accesseurs et des modifieurs
Les identificateurs des accesseurs et des modifieurs
des données membres d'une classe doivent être construits à
partir de l'identificateur de la donnée membre, préfixé
par Get ou Set, sans le m_ :
class CDate
{
// voir plus
haut
unsigned GetAn (void) const;
unsigned GetMois (void) const;
unsigned GetJour (void) const;
void SetAn (const unsigned
An);
void SetMois (const unsigned Mois);
void SetJour (const unsigned Jour);
//
}; // CDate |
Sommaire
Identificateurs des espaces
de noms
Faire précéder le nom de l'espace des
noms des lettres ns :
ou nsSysteme, nsImprim, etc...
Sommaire
Identificateurs des données
membres
Faire précéder le nom de la donnée
membre des caractères m_ :
class CTimer
{
CDelai m_Delai; |
Sommaire
Identificateurs des constantes
Afin de les reconnaître facilement, les identificateurs
des constantes devraient commencer par le préfixe Cst :
const unsigned CstSizeMax = 100;
enum {CstNoError, CstPileVide, CstPilePleine,
CstMemoireInsuffisante}; |
Les littéraux numériques sont à
éviter le plus possible dans les différents cas d'une instruction
switch.
Préférer des constantes comme par exemple :
enum {CasAdd = 'A', CasSubtr = 'S', CasModif
= 'M'};
//...
switch (Choix)
{
case CasAdd :
Add (...);
break;
case CasSubtr :
Subtr (...);
break;
} |
Cette convention est intéressante à
plusieurs titres, en particulier pour les comparaisons d'égalité.
Sommaire
Identificateurs
des prédicats ou variables booléennes
Les identificateurs de prédicats sont souvent
plus immédiatement lisibles s'ils sont préfixés de
Est
ou Is :
Sommaire
Accolades
Deux arrangements d'accolades sont autorisés,
choisissez celui qui vous convient le plus et tenez-vous à ce choix
!
Présentation
"K&R" (Kernighan and Richie)
if (...) {
// suite des
// instructions
} |
ou
for (...) {
// suite des
// instructions
} |
ou
class CClass {
// suite des
// instructions
}; // CClass |
Sommaire
Présentation "classique"
Les deux accolades sont alignées verticalement
:
if (...)
{
// suite des
// instructions
} |
ou
for (...)
{
// suite des
// instructions
} |
ou
class CClass
{
// suite des
// instructions
}; // CClass |
Sommaire
Terminaison
des classes, des fonctions, et des espaces de noms
Toujours rappeler en fin de classe, de fonction ou d'espace
de noms, leur identificateur :
class CClass
{
// suite des
// instructions
}; // CClass |
ou
void Projeter (...)
{
int i;
//...
} // Projeter() |
ou
namespace nsGraph
{
int i;
//...
} // nsGraph |
Exception : les fonctions qui tiennent sur une seule ligne :
void CDate::SetAn (const unsigned An) { m_An = An; }
void Derout (int) {} |
Sommaire
Déclarations et définitions
Déclarations
et définitions des classes
Chaque classe doit être déclarée
dans un fichier séparé, d'extension .h, et de nom identique
à l'identificateur de la classe :
// fichier CElement.h
#if !defined __CELEMENT_H__
#define __CELEMENT_H__
class CElement
{
// ...
CElement (...);
}; // CElement
#endif // __CELEMENT_H__ |
Cas particuliers : on regroupe parfois toute une
hiérarchie de classes dans un même fichier, qui a le nom de
la classe mère.
Les définitions des fonctions membres et des
opérateurs surchargés ne doivent pas apparaître
dans la déclaration (trop lourd au fur et mesure que la classe
se développe). Si les définitions des méthodes sont
courtes (moins de 3 ou 4 lignes par exemple), ou si la classe est générique,
leur code doit être placé en inline dans un fichier
de même nom et d'extension .hxx, lui-même inclus dans
le fichier .h, et possédant les directives d'inclusion
conditionnelle :
// fichier CElement.h
#if !defined __CELEMENT_H__
#define __CELEMENT_H__
class CElement
{
// ...
CElement (...);
}; // CElement
#include "CElement.hxx"
#endif // __CELEMENT_H__ |
et
// fichier CElement.hxx
#if !defined __CELEMENT_HXX__
#define __CELEMENT_HXX__
#include "CElement.h"
inline CElement::CElement (...)
{
// ...
} // CElement ()
// ...
#endif // __CELEMENT_HXX__ |
Dans le cas contraire, leur code doit être
placé dans un fichier de même nom et d'extension .cpp
ou .cxx (selon le compilateur).
Sommaire
Déclaration
et définition des namespace's
Chaque espace de noms doit être déclarée
dans un fichier séparé, d'extension .h, et de nom identique
à l'identificateur de l'espace :
// fichier nsBAO.h
#if !defined __NSBAO_H__
#define __NSBAO_H__
namespace nsBAO
{
// ...
void FctOutil (void);
} // nsBAO
#endif // __NSBAO_H__ |
Les définitions des fonctions et des opérateurs
surchargés ne doivent pas apparaître dans la déclaration
(trop lourd au fur et mesure que l'espace de noms se développe).
Si les définitions des fonctions sont courtes (moins de 3 ou 4 lignes
par exemple), si elles sont génériques ou si elles
sont très rarement appelées, leur code doit être placé
en inline dans un fichier de même nom et d'extension .hxx,
lui-même inclus dans le fichier .h, et possédant
les directives d'inclusion conditionnelle :
// fichier nsBAO.h
#if !defined __NSBAO_H__
#define __NSBAO_H__
namespace nsBAO
{
// ...
} // nsBAO
#include "nsBAO.hxx"
#endif // __NSBAO_H__ |
et
// fichier nsBAO.hxx
#if !defined __NSBAO_HXX__
#define __NSBAO_HXX__
#include "nsBAO.h"
namespace nsBAO
{
// ...
inline void FctOutil (void)
{
// ...
} // FctOutil()
} // nsBAO
#endif // __NSBAO_HXX__ |
Cette écriture a l'inconvénient de
nécessiter une indentation de la totalité du code inclus
dans l'espace des noms. Elle présente aussi le danger de surcharger
involontairement une fonction de profil différent déclarée
dans le fichier .h. On peut lui préférer :
// fichier nsBAO.hxx
#if !defined __NSBAO_HXX__
#define __NSBAO_HXX__
#include "nsBAO.h"
inline void nsBAO::FctOutil (void)
{
// ...
} // FctOutil()
#endif // __NSBAO_HXX__ |
Le danger de cette seconde écriture est d'oublier
le préfixage de la fonction par nsBAO::
Sommaire
Déclaration
et définition des fonctions
Tous les paramètres données doivent être
précédés du mot réservé const,
sauf si certaines fonctions C mal prototypées doivent elles-mêmes
être appelées. Les éventuelles valeurs par défaut
doivent apparaître dans la déclaration. En revanche elles
sont interdites dans la définition. Cependant, vous devrez les indiquer
en commentaires dans la définition (à la lecture du corps
de la fonction, il est important de se souvenir des valeurs par défaut
des paramètres). Bien qu'ils soient facultatifs, les identificateurs
des paramètres formels devront être présents dans la
déclaration des fonctions (seul le type est exigé par le
compilateur). Tous les paramètres données d'un autre type
qu'un type de base (int, short, etc...) doivent être passés
par référence :
// fichier f.h
// ...
namespace nsPrive
{
void Fct (const int n, const int Structure =
0);
void TransfererImage (const CImage & Image,
...);
} // nsPrive |
// fichier f.cxx
#include "f.h"
void nsPrive::Fct (const int n, const int Structure /* = 0 */)
{
// ...
} // Fct() |
Sommaire
Schéma alternatif
Les indications ci-dessous peuvent parfois être
contradictoires. Dans ce cas, il est conseillé d'appliquer les différentes
règles dans l'ordre dans lequel elles sont présentées.
Rupture de séquence
Lorsqu'un des deux blocs "alors" ou "sinon" se termine
par une rupture de séquence (throw ...; ou return ...;
ou exit (...);), placer ce bloc en tête (en inversant éventuellement
la condition) et supprimer le bloc "sinon". Par exemple :
if (EstValide (Param))
{
cout << "paramètre valide"
<< endl;
TraiterSuite ();
}
else
{
cout << "paramètre invalide" <<
endl;
return false;
} |
doit être remplacé par :
if (!EstValide (Param))
{
cout << "paramètre invalide" <<
endl;
return false;
}
cout << "paramètre valide" << endl;
TraiterSuite (); |
Sommaire
Déséquilibre
des blocs "alors" et "sinon"
Si le bloc "sinon" est beaucoup plus court que le bloc
"alors" (1 ou 2 lignes contre une dizaine au moins), les permuter en inversant
la condition.
Sommaire
Simplification de la condition
Lorsqu'un schéma alternatif comporte les blocs
"alors" et "sinon", choisir la condition de test la plus simple (par exemple
en évitant une négation), quitte à inverser les contenus
des blocs. Par exemple :
if (!EstValide (Param))
cout << "paramètre invalide" <<
endl;
else
cout << "paramètre valide"
<< endl; |
devrait être remplacé par :
if (EstValide (Param))
cout << "paramètre valide"
<< endl;
else
cout << "paramètre invalide" <<
endl; |
Sommaire
L'opérateur ? :
Lors de l'évaluation d'une expression, utiliser
chaque fois que cela est possible l'opérateur ? : plutôt
que l'instruction
if () ...; else par exemple :
cout << "résultat : x " << ((x > 0.0) ? "positif"
: "négatif ou nul") << endl; |
au lieu de :
cout << "résultat : ";
if (x > 0.0)
cout << "x positif";
else
cout << "x négatif ou nul";
cout << endl; |
ou encore :
printf ("Valeur absolue de %d = %d\n", x, (x >= 0.0) ? x : -x); |
au lieu de :
int xProv;
if (x < 0)
xProv = -x;
else
xProv = x;
printf ("Valeur absolue de %d = %d\n", x, xProv); |
Sommaire
Divers
Variables
intermédiaires - opérateurs spécifiques
Eviter de déclarer des variables intermédiaires
inutiles. On peut les utiliser pour rendre le programme lisible au moment
de la mise au point, mais elles doivent être éliminées
ultérieurement. De la même façon, utiliser les
possibilités du C/C++ au maximum : opérateurs ++
et --, (en préférant la pré-incrémentation/décrémentation
++i
à
la post-incrémentation/décrémentation
i++),
variable entière non nulle équivalente à
VRAI,
etc... Par exemple, le programme suivant, qui affiche à l'envers
les n valeurs d'un tableau Tab et réinitialise n à
0 :
for (int i = n; i > 0; i--) cout << Tab [i - 1];
n = 0; |
sera avantageusement remplacé par :
for (; n; ) cout << Tab [--n]; |
De même :
sera avantageusement remplacé par :
Sommaire
Vérification des paramètres
Lorsqu'une commande supporte ou nécessite des
paramètres au lancement, la première chose que doit faire
le programme est de vérifier leur validité :
int main (int argc, char * argv [])
{
// vérifier argc et éventuellement
argv
// suite
} // main() |
Sommaire
Utilisation des constantes
Les constantes explicites (littéraux numériques)
sont à éviter le plus possible : elles doivent être
remplacées par des macros (c'est du C, à éviter en
C++) ou mieux, par des constantes
symboliques. Cette "paramétrisation" des programmes permet une
maintenance beaucoup plus facile. Par exemple :
à remplacer par :
#define LONG_TAB 12
char Tab [LONG_TAB]; |
ou, encore mieux :
const int CstLgTab = 12;
char Tab [CstLgTab]; |
En principe, seules les constantes 0, 1, -1 devraient
apparaître en clair dans un programme.
Sommaire
Constante 0 ou NULL ?
Contrairement à ce qui est demandé ci-dessus,
la constante 0 doit être préférée à la
macro NULL en C++, en raison de possibles définitions multiples
de cette dernière dans de multiples fichiers. Il faut en effet rappeler
que le C++ sait toujours transtyper et convertir la constante universelle
entière 0, mais pas forcément la constante symbolique NULL,
peut-être elle-même déjà transtypée.
Sommaire
Objets sur
la pile, objets en mémoire dynamique
Un objet créé sur la pile est présent
en mémoire depuis le moment où il est défini jusqu'à
la sortie du bloc qui le contient. Les raisons de créer un objet
en mémoire dynamique plutôt que sur la pile d'exécution
sont :
-
l'espace mémoire occupé par l'objet doit être libéré
avant d'atteindre la fin du bloc dans lequel il a été défini
(il vaudrait mieux faire un bloc),
-
l'objet doit exister au-delà du bloc dans lequel il a été
créé,
Dans tous les autres cas, il faut utiliser la pile d'exécution.
Exemples :
const int CstMaxTab = 128;
// ...
void f (void)
{
CX * Tab = new char [CstMaxTab]; // absurde
!!!
//...
delete [] Tab;
// risque d'être oublié !!!
} // f() |
mais :
CX * f (void)
{
CX Tab [CstMaxTab];
CX * PtrTab = Tab;
return PtrTab;
// une horreur : renvoie l'adresse d'une zone
// détruite lors du retour de la fonction
} // f() |
et
void f (void)
{
int Lg;
cin >> Lg;
CX * Tab = new CX [Lg]; //
incontournable !!!
// ...
delete [] Tab;
// à ne pas oublier !!!
} // f() |
Pour libérer la mémoire le plus vite
possible :
void f (void)
{
CX * Tab = new CX [CstMaxTab];
// ...
delete [] Ligne;
// suite de la fonction
} // f() |
mais, plus efficace :
void f (void)
{
{
CX Tab [CstMaxTab];
// ...
} // l'objet ligne est détruit
ici
// suite de la fonction
} // f() |
Sommaire
Constructeurs
Utiliser le plus possible la phase
d'initialisation du constructeur plutôt que des affectations. Le
code est beaucoup plus efficace. Par exemple, pour la classe suivante :
class CIndividu
{
CDate m_DNaissance;
CDate m_DEmbauche;
int m_Taille;
public :
CIndividu (const CDate & DNaissance,
const CDate & DEmbauche,
const int Taille);
}; // CIndividu |
le constructeur :
inline CIndividu::CIndividu (const CDate & DNaissance,
const CDate & DEmbauche,
const int Taille);
: m_DNaissance (DNaissance),
m_DEmbauche (DEmbauche),
m_Taille
(Taille) {}
}; // CIndividu |
est à préférer à :
inline CIndividu::CIndividu (const CDate & DNaissance,
const CDate & DEmbauche,
const int Taille)
{
m_DNaissance = DNaissance;
m_DEmbauche = DEmbauche;
m_Taille = Taille;
} // CIndividu() |
Sommaire
Test d'égalité
Lors d'un test d'égalité, placer à
gauche de l'opérateur l'opérande qui n'aurait pas le droit
d'être à gauche d'une affectation, s'il y en a un. Par exemple
est à préférer à :
car la frappe malencontreuse de l'affectation au lieu de la comparaison
provoque une erreur de syntaxe. Dans le sens contraire, l'erreur d'exécution
est très difficilement détectable.
Le nommage des constantes indiqué plus
haut permet d'appliquer cette règle plus facilement :
if (CstNoError == CodeErreur) |
Sommaire
Affectation
Le résultat de l'affectation est une valeur qui peut immédiatement
être réutilisée
-
pour une nouvelle affectation :
pour un test :
à ne pas confondre avec la comparaison, qui n'a rien à
voir :
Sommaire

© D. Mathieu
mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique