C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Sens de const
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 3:10 am    Post subject: Sens de const Reply with quote



Bonjour,

Je voudrais savoir quel sens vous mettez derriere le mot clé "const", ou
plutot quel contrat une fonction qui a des parametres const doit remplir.

Pour être plus clair, voici le cas qui m'interesse plus particulierement :
nous avons une classe "iterator" qui me permet d'itérer sur une structure de
donnée. Un "iterator" a de bonnes raisons (qui ne sont pas discutables Smile)
d'être un peu lourd à copier. Maintenant imaginons une fonction
"nbElementsAfter" qui fait ca :

int nbElementsAfter(iterator& it)
{
int nb = 0;
while(it.next()) nb++;
for(int i=0; i return nb;
}

Est-ce que cette fonction doit prendre un iterator& ou un const iterator& ?
Lequel de ces contrats vous semble le plus sensé pour une fonction qui prend
un const iterator& : "je ne modifierai pas l'iterateur" ou "l'iterateur
pointera au même endroit avant et apres l'appel" (ou encore autre chose ?) ?

Merci

--
Vincent


Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 4:02 am    Post subject: Re: Sens de const Reply with quote



On Sat, 7 Jan 2006 19:10:46 -0800, "Vincent Lascaux" :

Quote:
int nbElementsAfter(iterator& it)
{
int nb = 0;
while(it.next()) nb++;

J'imagine que "next()" est une fonction membre non-const, i.e. elle
modifie "it". Par conséquent, "it" ne peut pas être const. Et, comme
on n'a pas le choix, la discussion s'arrête là.

Au fait, si tu appelles ton objet "iterator", il vaudrait mieux lui
mettre des opérateurs ++ et -- au lieu de next() et prev().


Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 4:03 am    Post subject: Re: Sens de const Reply with quote



On Sat, 7 Jan 2006 19:10:46 -0800, "Vincent Lascaux" ::

Quote:
Est-ce que cette fonction doit prendre un iterator& ou un const iterator& ?

Accessoirement, je te conseillerais d'écrire "iterator const&", il y a
moins de chance de confondre avec "const_iterator&".


Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 4:10 am    Post subject: Re: Sens de const Reply with quote

Quote:
int nbElementsAfter(iterator& it)
{
int nb = 0;
while(it.next()) nb++;

J'imagine que "next()" est une fonction membre non-const, i.e. elle
modifie "it". Par conséquent, "it" ne peut pas être const. Et, comme
on n'a pas le choix, la discussion s'arrête là.

int nbElementsAfter(const iterator& const_it)
{
iterator& it = const_cast<iterator&>(const_it);

int nb = 0;
while(it.next()) nb++;
for(int i=0; i return nb;
}

Quote:
Au fait, si tu appelles ton objet "iterator", il vaudrait mieux lui
mettre des opérateurs ++ et -- au lieu de next() et prev().

En fait la classe est plus compliquée, on a plusieurs façons de déplacer
l'itérateur... Je voulais juste avoir un exemple simple (en fait il n'y a
pas non plus de nbElementsAfter, mais une fonction qui utilise l'iterateur
pour lire un certains nombres d'élements et le remet à sa place.

--
Vincent



Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 4:16 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 20:10:45 -0800, "Vincent Lascaux"
<nospam (AT) nospam (DOT) org>:

Quote:
int nbElementsAfter(const iterator& const_it)
{
iterator& it = const_cast<iterator&>(const_it);

int nb = 0;
while(it.next()) nb++;

C'est un comportement indéfini.
const_cast<> sert à peu près uniquement à appeler une fonction qui ne
modifie pas l'objet, mais déclarée non-const par erreur.
iterator::next() ne répond pas à cette définition (puisqu'elle modifie
l'objet), donc il s'agit ici d'un abus de const_cast<>.

Le code que tu proposes n'est pas valide ; il ne fait donc pas partie
des possibilités.


Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 5:11 am    Post subject: Re: Sens de const Reply with quote

Quote:
int nbElementsAfter(const iterator& const_it)
{
iterator& it = const_cast<iterator&>(const_it);

int nb = 0;
while(it.next()) nb++;

C'est un comportement indéfini.

Ah bon ? Je trouve personnellement que c'est dommage qu'on ne puisse pas
utiliser const dans ce cas. Du coup il y a pas mal de fonctions qui ne
comportent plus de const dans leur signature parcequ'elles ont besoin
d'appeler des fonctions comme nbElementsAfter. Si on pouvait avoir "int
nbElementsAfter(const iterator&)" comme signature, on pourrait avoir des
const dans les parametres des fonctions qui l'appelle et avoir des
vérifications par le compilateur que la fonction retourne l'iterateur dans
l'état dans lequel elle l'a trouvé.

Quelle est la raison de cette interdiction de faire des const_cast ? C'est
pour laisser plus de liberté d'optimisation au compilateur ? Je croyais
qu'il n'avait pas le droit de faire d'optimisation basée sur la "constness"
d'une expression sans avoir vérifié qu'il n'y avait pas de const_cast dans
les fonctions appelées...

--
Vincent



Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 5:21 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 21:11:04 -0800, "Vincent Lascaux" :

Quote:
Quelle est la raison de cette interdiction de faire des const_cast ?

Parce que const_cast<> n'est pas un opérateur de conversion à
proprement parler, mais un moyen de dire au compilateur "Je soussigné
le programmeur, m'engage à ce que tel code ne modifie pas telle
variable, même si toi, le compilateur, tu ne peux pas t'en rendre
compte."
Si tu romps cet engagement, i.e. si tu mens, le résultat est indéfini.

C'est un peu la même chose pour reinterpret_cast<> : tu peux t'en
servir pour dire "J'affirme que tel pointeur pointe en fait sur une
variable de tel type.", mais si c'est un mensonge, le résultat est
indéfini.

Quote:
C'est pour laisser plus de liberté d'optimisation au compilateur ?

Il y a aussi de ça.

int main()
{
int const n= 42;
int& ptr_n= const_cast<int>(n);
ptr_n= 0;
cout << n << endl;
}

Le programme ci-dessus a un comportement indéfini : il peut afficher à
peu près n'importe quoi. En pratique, il y a de fortes chances pour
qu'il affiche 0 ou 42, suivant le compilo et les options de
compilation.



Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 5:23 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 19:10:46 -0800, "Vincent Lascaux" :

Quote:
Un "iterator" a de bonnes raisons (qui ne sont pas discutables Smile)
d'être un peu lourd à copier.

Note que tu pars d'emblée sur de mauvaises bases : un itérateur au
sens de la STL ("iterator") est un objet très souvent copié. On ne le
passe quasiment jamais par référence const.


Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 5:35 am    Post subject: Re: Sens de const Reply with quote

Quote:
"Je soussigné
le programmeur, m'engage à ce que tel code ne modifie pas telle
variable, même si toi, le compilateur, tu ne peux pas t'en rendre
compte."

Je voudrais dire "Je soussigné le programmeur m'engage à ce qu'apres
l'execution de la fonction, la variable aura toujours la même valeur" (au
sens de const, ie sauf mutables).
Il n'y a donc pas moyen de faire ca ? C'est dommage parceque j'ai le
sentiment que c'est ce qui est important. En tant qu'utilisateur de
nbElementsAfter, ce qui m'importe c'est que la fonction me retourne la bonne
valeur et que je puisse continuer à travailler avec mon itérateur. Le fait
qu'en interne elle modifie temporairement l'iterateur ne m'interesse pas
vraiment. J'ai du mal à voir un cas où il est important d'avoir dans le
contrat d'une fonction "ne modifie pas l'objet" plutot que le moins fort
"retourne l'objet dans l'état d'origine". Const impose une contrainte à la
fonction qui me semble trop forte et me limite dans l'implémentation de
nbElementsAfter sans que j'ai l'impression que ca n'apporte quoi que ce soit
à l'appelant.

--
Vincent



Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 5:44 am    Post subject: Re: Sens de const Reply with quote

Quote:
Note que tu pars d'emblée sur de mauvaises bases : un itérateur au
sens de la STL ("iterator") est un objet très souvent copié. On ne le
passe quasiment jamais par référence const.

Et qui dit que je fais un "iterator" au sens de la STL ? J'aurais du donner
un autre nom à cette classe Smile
De toutes façons, le problème n'est pas là... C'est pas très difficile de
trouver d'autres exemples. Pour une classe d'entiers long, utilisée pour des
entiers de plusieurs ko par exemple,

void printNext(LongInt& val)
{
++val;
std::cout << val;
--val;
}

Comme tout exemple minimaliste, cette fonction est d'une utilité douteuse...
Mais il est concevable qu'en moyenne, le code ci-dessus soit plus rapide que
le code suivant (qui peut en plus poser des problemes de mémoire à cause de
la création du temporaire "val+1")

void printNext(const LongInt& val)
{
std::cout << val + 1;
}

C'est cher payer pour conserver le const...

--
Vincent



Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 6:07 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 21:35:47 -0800, "Vincent Lascaux" :

Quote:
Je voudrais dire "Je soussigné le programmeur m'engage à ce qu'apres
l'execution de la fonction, la variable aura toujours la même valeur"

Je comprends l'idée, mais la formulation me paraît imprécise.
Méfie-toi des mots comme "toujours" qui ont plusieurs sens légèrement
différents.

Car un des problèmes est dans cette subtilité : l'objet n'a pas
toujours la même valeur ; à un moment de l'exécution de la fonction,
il a une valeur différente.

Le problème le plus immédiat : s'assurer que toutes les opérations
"next()" sont réversibles en temps normal. Ça demande une connaissance
du fonctionnement de iterator, ou au moins un contrat assez
restrictif. AMHA, nbElementsAfter serait mieux comme fonction membre.

Second problème : s'assurer que le contrat ("La valeur est la même à
la fin de la fonction") est bien respecté en cas d'exception.
Si next() et prev() sont déclarées "nothrow", tout va bien.
Sinon, je ne sais pas comment tu comptes t'en sortir.

Troisième problème : s'assurer que pendant l'exécution de la fonction,
aucun code ne s'attend à voir la valeur de départ dans l'objet.
Bien évidemment, le cas du multithread vient tout de suite à l'esprit
(et j'ai appris à mes dépens que sous Windows au moins, on travaille
parfois en multithread sans trop s'en rendre compte), mais il est
possible d'imaginer des cas où le code même de next() (ou de prev())
s'attend à ce que l'objet passé en argument ait sa valeur de départ.


Pour résoudre ton problème, je ne vois pas vraiment d'autre solution
que la copie, sinon de l'objet "iterator", au moins d'une partie de
cet objet : extraire de l'objet "iterator" un sous-objet copiable et
contenant assez d'information pour calculer la réponse.


7h07 : une heure à pleurer.


Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 6:13 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 21:44:42 -0800, "Vincent Lascaux" :

Quote:
J'aurais du donner un autre nom à cette classe

Effectivement.

Quote:
void printNext(LongInt& val)
{
++val;
std::cout << val;
--val;
}

Cf mon message de 7h07.

Quote:
Comme tout exemple minimaliste, cette fonction est d'une utilité douteuse...

Je ne te le fais pas dire. En fait, j'avoue n'avoir jamais rencontré
le problème dans une application réelle.

Quote:
Mais il est concevable qu'en moyenne, le code ci-dessus soit plus rapide que
le code suivant

Va savoir... Qu'est-ce qui prouve qu'une décrémentation sera plus
rapide qu'une copie ?



Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 6:41 am    Post subject: Re: Sens de const Reply with quote

Quote:
Je voudrais dire "Je soussigné le programmeur m'engage à ce qu'apres
l'execution de la fonction, la variable aura toujours la même valeur"

Je comprends l'idée, mais la formulation me paraît imprécise.
Méfie-toi des mots comme "toujours" qui ont plusieurs sens légèrement
différents.

Je veux dire "l'état de la variable après l'execution de la fonction est le
même qu'avant l'execution de la fonction"

Quote:
Le problème le plus immédiat : s'assurer que toutes les opérations
"next()" sont réversibles en temps normal. [...]

Second problème : s'assurer que le contrat est bien respecté
en cas d'exception. [...]

Ces deux problemes sont là aussi avec la version non const de
nbElementsAfter puisqu'on s'attend là aussi à ce que l'itérateur ne soit pas
déplacé (même si le compilateur ne le sait pas lui).
Avoir une fonction qui ne remplit pas son contrat (ie un bug) c'est mal,
mais bon, ca arrive, et je vois pas pourquoi on devrait s'inquieter plus sur
ce bug que sur un autre (s'assurer que nbElementsAfter retourne bien la
bonne valeur est aussi assez difficile).
Pour la petite info, en mode debug, on utilise RAII pour prendre l'état de
l'objet à l'entrée de la fonction et vérifier à la sortie que c'est le même.

Quote:
Troisième problème : s'assurer que pendant l'exécution de la fonction,
aucun code ne s'attend à voir la valeur de départ dans l'objet.
Bien évidemment, le cas du multithread vient tout de suite à l'esprit

Je n'est pas à me soucier de probleme de multi threading pour le code sur
lequel je travaille, et je ne suis pas un expert dans ce domaine, mais si
c'était le cas, il est clair que nbElementsAfter devrait "locker"
l'itérateur comme pour le modifier dans le bloc de la fonction.

Quote:
(et j'ai appris à mes dépens que sous Windows au moins, on travaille
parfois en multithread sans trop s'en rendre compte),

Tu peux donner quelques détails ? Je suis pas sur de comprendre...

Quote:
mais il est
possible d'imaginer des cas où le code même de next() (ou de prev())
s'attend à ce que l'objet passé en argument ait sa valeur de départ.

T'aurais un exemple ?

--
Vincent



Back to top
Vincent Lascaux
Guest





PostPosted: Sun Jan 08, 2006 7:06 am    Post subject: Re: Sens de const Reply with quote

Quote:
Qu'est-ce qui prouve qu'une décrémentation sera plus
rapide qu'une copie ?

Rien ne le prouve, mais j'ai en tête un operateur ++ qui fait quelque chose
comme (sur une représentation en base Base)

int i = 0;
while (i val[i++] = 0;
if(i == val.size())
val.push_back(1);
else
val[i]++;

Si on prend un nombre aléatoire, la probabilité de modifier exactement n
chiffres est (Base-1)/Base^n (si je ne m'abuse). La moyenne est donc
(Base-1)*Sum(n/Base^n)
Pour un nombre de 100 chiffres, avec Base = 256, on va modifier en moyenne
moins de 1.004 élements, contre 100 pour une copie... Il y a forcément une
taille de nombre à partir de laquelle mon opérateur ++ est plus rapide
qu'une copie de l'intégralité du nombre.

--
Vincent



Back to top
Fabien LE LEZ
Guest





PostPosted: Sun Jan 08, 2006 7:14 am    Post subject: Re: Sens de const Reply with quote

On Sat, 7 Jan 2006 22:41:04 -0800, "Vincent Lascaux" :

Quote:
Ces deux problemes sont là aussi avec la version non const de
nbElementsAfter puisqu'on s'attend là aussi à ce que l'itérateur ne soit pas
déplacé (même si le compilateur ne le sait pas lui).

Sans doute. Mais j'essayais d'expliquer pourquoi le langage ne
contient rien pour indiquer que la valeur est la même à la fin et au
début.

Quote:
(et j'ai appris à mes dépens que sous Windows au moins, on travaille
parfois en multithread sans trop s'en rendre compte),

Tu peux donner quelques détails ? Je suis pas sur de comprendre...

Par exemple, un code appelé en callback par un timer multimédia
s'exécute dans un thread différent de celui qui a créé le timer.


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.