OVH Cloud OVH Cloud

parametres simples en const ?

70 réponses
Avatar
JBB
Bonjour

Lorsque je crée une fonction qui prend un entier en paramètre je fais quelque chose du genre:

int Double( int x)
{
return 2*x;
}

Je me demande s'il il n'est pas plus sage de faire
int Double( const int x)
{
return 2*x;
}
dans la mesure ou je n'ai pas l'intention de modifier x dans le corps.

Cela permettrait d'eviter certaines erreurs (comme affecter x par erreur), par exemple :
int Rapport(const int a,const int b)
{
bool bDivisionParZero = ( b = 0);
if (bDivisionParZero )
{
//exception
}
else
{
return a / b;
}
}
Si b est declare const ce code ne compile pas.
ou alors
int rapport(const int nombreElements,Truc * Tableau)
{
for (;nombreElements >0; nombreElements--)
{
...
}

//renvoyer le nombre d'elements traites
return nombreElements;
}

Est ce une pratique courrante?

10 réponses

1 2 3 4 5
Avatar
Herode
Bonjour à tous.

Je vais peut-être poser une question bête, mais voici :

Je vois bien l'intérêt de déclarer const un tel argument
(programmation défensive = préférer les erreurs de compilations aux
erreurs à l'exécution, dont chacun sait qu'elles sont toujours lieu
en présence de M. Demesmaeker).

A l'inverse, je ne comprends pas en quoi cette déclaration const peut
gêner. Autrement dit : qu'est-ce qui justifie de telles réticences
face à ce genre de déclarations ?
Avatar
Fabien LE LEZ
On Fri, 03 Mar 2006 15:38:18 +0100, Aurélien Barbier-Accary :

const int i = 3;
cout << "le double de " << i << " est " << Double(i) << endl;

-> un bon compilateur doit signaler un warning !!


Non. L'objet i ne peut pas être modifié, puisqu'il est passé par
copie.

Avatar
Sylvain
Marc Boyer wrote on 03/03/2006 12:24:
devrait lire return 2.0 * x;


Et pourquoi ce passage en double ?


j'ai été abusé par le "Double" (nom de fonction) que j'ai lu comme
"double" (type retour), dans un tel cas il fait sens de forcer une
multiplication flottante ; j'ai annulé mon post après avoir relu.

(et se coder directement (x << 1))


Sur ?


j'ai du mal à imaginer ce qui pourrait en faire douter.

ici le type retour a la même taille que l'argument donc donc le meilleur
codage (si on se soucit des perfs); une fonction long Double(int)
devrait elle être codée { return 2L * x; } (que "int" soit de la taille
de long ou non).

Sylvain.


Avatar
Sylvain
Marc Boyer wrote on 03/03/2006 12:24:

devrait lire return 2.0 * x;


Et pourquoi ce passage en double ?


j'ai été abusé par le "Double" (nom de fonction) que j'ai lu comme
"double" (type retour), dans un tel cas il fait sens de forcer une
multiplication flottante ; j'ai annulé mon post après avoir relu.

(et se coder directement (x << 1))
Sur ?



j'ai du mal à imaginer ce qui pourrait en faire douter.

ici le type retour a la même taille que l'argument donc le meilleur
codage (si on se soucie des perfs); une fonction long Double(int)
devrait elle être codée { return 2L * x; } pour éviter l'overflow (si
"int" n'a pas la taille de "long").

Sylvain.


Avatar
James Kanze
Marc Boyer wrote:
Le 03-03-2006, Marc Duflot a écrit :
Marc Boyer wrote:
On pourrait, mais le problème est que ce const apparaît dans la
signature de la fonction alors que c'est une question
d'implantation.
Non, il est permis (et conseillé) de déclarer dans l'interface




int Double (int x);



et d'utiliser dans la définition



int Double (const int x)
{
return 2*x;
}



Je ne savais pas. Merci de l'information.


Au cas où, sais-tu si c'est spécifique C++ ou si C admet la
même chose ?


Oui. §6.7.5.3/15: « (In the determination of type compatibility
and of a composite type, each parameter declared with function
or array type is taken as having the adjusted type and each
parameter declared with qualified type is taken as having the
unqualified version of its declared type.) »

Dans les interfaces, il ne devrait jamais y avoir de const à
cet endroit.



C'est bien ce qu'il me semblait.


C-à-d que c'est une bonne convention. La norme permet le const,
mais l'ignore.

--
James Kanze
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



Avatar
James Kanze
Aurélien Barbier-Accary wrote:
Le 03-03-2006, Marc Duflot a écrit :
Non, il est permis (et conseillé) de déclarer dans l'interface
int Double (int x);
et d'utiliser dans la définition
int Double (const int x)
{
return 2*x;
}




const int i = 3;
cout << "le double de " << i << " est " << Double(i) << endl;


-> un bon compilateur doit signaler un warning !!


J'éspère que non, vue que c'est la forme conseillée par
certaines règles de programmation.

Pourquoi est-ce qu'il doit y avoir d'avertissement ?

Moi je plaide pour :
int Double(const int x);
ça fonctionne avec int et avec const int


Et signifie exactement la même chose. Étant donné que le
compilateur ignore le const ici, je ne vois pas l'intérêt à le
mettre. (En fait, je ne le mets jamais, et je n'ai jamais vu du
code qui le mettait.)

Dans le cas de « int Double( int const x ) {...} », ça se
discute. Je vois surtout de bons arguments pour mettre le const.
Mais j'avoue que je ne le mets jamais, et que je n'ai prèsque
jamais vu dans le code des autres.

--
James Kanze
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



Avatar
James Kanze
Herode wrote:

Je vais peut-être poser une question bête, mais voici :


Je vois bien l'intérêt de déclarer const un tel argument
(programmation défensive = préférer les erreurs de
compilations aux erreurs à l'exécution, dont chacun sait
qu'elles sont toujours lieu en présence de M. Demesmaeker).


A l'inverse, je ne comprends pas en quoi cette déclaration
const peut gêner. Autrement dit : qu'est-ce qui justifie de
telles réticences face à ce genre de déclarations ?


Attention ! Il s'agit de deux choses différentes. Dans une
déclaration qui n'est pas une définition, le compilateur ignore
le const. Je n'y vois aucun intérêt à le mettre, dans la mesure
où il n'apporte ni de sécurité ni d'information supplémentaire à
celui qui lit le code. Dans une définition de fonction, c'est
autre chose. Je vois bien l'argument pour le mettre, et pas
vraiment d'argument contre. N'empèche que je ne vois personne (y
compris moi-même) qui le met. Je suppose que c'est simplement
parce que la localité de l'objet est telle qu'on peut voir
immédiatement toutes les modifications (ou l'absence de
modification) sans se casser la tête. (Encore que... si on le
passe par référence ou par adresse à une autre fonction... le
const pourrait éviter des erreurs.)

--
James Kanze
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

Avatar
James Kanze
Sylvain wrote:
Marc Boyer wrote on 03/03/2006 12:24:


devrait lire return 2.0 * x;




Et pourquoi ce passage en double ?



j'ai été abusé par le "Double" (nom de fonction) que j'ai lu
comme "double" (type retour), dans un tel cas il fait sens de
forcer une multiplication flottante ; j'ai annulé mon post
après avoir relu.


C'est vrai que le nom n'est pas superbe. (Mais
réalistiquement... je crois que l'intention n'était que d'avoir
un exemple simple, et non de donner du code de production. Je
doute fort que dans un vrai projet, on aurait jamais une telle
fonction.)

(et se coder directement (x << 1))
Sur ?




j'ai du mal à imaginer ce qui pourrait en faire douter.


Faire douter quoi ? Si je veux multiplie par deux, je multiplie
par deux, c-à-d « 2 * x ».

ici le type retour a la même taille que l'argument donc le
meilleur codage (si on se soucie des perfs);


Tu as de mesures à l'appui, j'espère, si tu parles de la
performance. Une application où une telle obfuscation faisait la
différence entre une performance acceptable et une performance
non-acceptable.

J'ai eu réelement une fois à mesurer la différence entre « 127 *
x » et « x << 7 - 1 ». Avec Sun CC sur Sparc, c'est le premier
qui était le plus rapide (bien que de très peu). Et ça, sur une
machine sans multiplication cablée.

une fonction long Double(int)


devrait elle être codée { return 2L * x; } pour éviter
l'overflow (si "int" n'a pas la taille de "long").


Et même si int l'est, de façon à être portable. Ça fait partie
des précautions qu'on prend d'office dès qu'on utilise un
mélange de types.

Mais quel rapport avec « x << 1 » ?

--
James Kanze
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



Avatar
James Kanze
EjderHa wrote:

Je me demande s'il il n'est pas plus sage de faire



int Double( const int x) { return 2*x; }



dans la mesure ou je n'ai pas l'intention de modifier x dans
le corps.



oui si tu est un inconditionnel de la programmation défensive.
Personnelement je ne vois pas vraiment la différence, de toute
manière pour un paramètre passez par valeur on travail avec
une copie dans la pile.


Dans une fonction aussi petite que celle-ci, il n'en y a
sûrement pas. Si la fonction est plus longue, il peut être
intéressant d'empécher la modification accidentale d'une valeur
qu'on crois ne pas modifier.

Moi j'en profite pour éviter de déclarer d'autres variables
locales les paramètres faisant déjà l'affaire. (dans un
parcourt de tableau par exemple).


int sum (int T[], int n)
{
int r = 0; while (n>0) r += T[--n];
return r;
}


Ça dépend des cas. Une chose est sûr : je n'écrirai jamais la
fonction comme tu l'as fait, avec une déclaration, une boucle,
et le corps de la boucle sur la même ligne.

Mais quel rapport ? Si tu veux modifier une variable, tu ne la
déclares const. La question est : qu'est-ce qu'il vaut mieux
faire quand tu ne comptes pas la modifier ?

[...]
int Rapport(const int a,const int b)
{
bool bDivisionParZero = ( b = 0);
if (bDivisionParZero )
{
//exception
}
else
{
return a / b;
}
}
Si b est declare const ce code ne compile pas.



ton bool bDivisionParZero faudrait peut-etre le remplacer par
(b==0), et la ca devrait compiler (en rajouter la levée de
l'exception).


C'est exactement son point. En déclarant b const, le compilateur
détecte une erreur.

sinon oui tu affecte 0 à b que t'a déclaré comme variable
locale constante. il faut savoir ce que tu veut une constante
ou pas constante, faut faire un choix.


Il a fait le choix. Il a aussi fait un typo -- exprès, ici, pour
nous montrer le type d'erreur qu'on pourrait détecter.

[...]
mais ca sert pour des variables globales, pour des pointeurs
vers constante, ou des références vers constante. Je ne vois
pas l'interêt pratique de mettre un paramètre simple en const.


Et cependant, il vient d'en monter un exemple.

--
James Kanze
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


Avatar
Marc Boyer
Tout d'abord, desole pour l'encodage, ca marche moyen
en ce moment.

Le 03-03-2006, Herode a écrit :
A l'inverse, je ne comprends pas en quoi cette déclaration const peut
gêner. Autrement dit : qu'est-ce qui justifie de telles réticences
face à ce genre de déclarations ?


Mes reticences a ce type de chose dans la *declaration* de la
fonction sont:
1) que le jour ou on decide justement d'utiliser ce parametre
dans le code, on ne peut plus...
2) Il y a un enorme existant, et on a des habitudes de lecture
rapide apres des annees de codage. Voire apparaitre ce const
va AMHA gener la lecture, parce qu'il est inhabituel sans
rien apporter.

Mais, maintenant que je sais qu'on peut ne pas le mettre dans
la declaration et le mettre dans la definition, je n'ai aucune
reticence a ce que ce soit utilise dans la definition de la
fonction.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exiter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)

1 2 3 4 5