Bonjour,
je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens):
- elle force la vérification que n ne sera pas
modifiée à l'intérieur de fct.
- elle force un passage sans recopie de n
( plus génant pour un vrai objet)
- elle évité d'avoir à réfléchir si INT est un POD ou un objet
complexe et hésiter entre la forme 1. et 2.
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1.
pour les objets. J'ai du mal à donner des arguments contre la forme 1
(au delà de la lourdeur de la notation).
----- Original Message ----- From: "David F." Newsgroups: fr.comp.lang.c++ Sent: Saturday, October 15, 2005 1:04 PM Subject: const & sur les POD
Bonjour, je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens): - elle force la vérification que n ne sera pas modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n ( plus génant pour un vrai objet)
Plus génant ? Au contraire passer un objet par référence offre un gain : pas de construction ni de destruction de l'objet.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets. J'ai du mal à donner des arguments contre la forme 1 (au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée par les avantages offerts.
-- -Stan
----- Original Message -----
From: "David F." <dfleury2@libertysurf.fr>
Newsgroups: fr.comp.lang.c++
Sent: Saturday, October 15, 2005 1:04 PM
Subject: const & sur les POD
Bonjour,
je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens):
- elle force la vérification que n ne sera pas
modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n
( plus génant pour un vrai objet)
Plus génant ?
Au contraire passer un objet par référence offre un gain :
pas de construction ni de destruction de l'objet.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet
complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première
forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1.
pour les objets. J'ai du mal à donner des arguments contre la forme 1
(au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée
par les avantages offerts.
----- Original Message ----- From: "David F." Newsgroups: fr.comp.lang.c++ Sent: Saturday, October 15, 2005 1:04 PM Subject: const & sur les POD
Bonjour, je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens): - elle force la vérification que n ne sera pas modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n ( plus génant pour un vrai objet)
Plus génant ? Au contraire passer un objet par référence offre un gain : pas de construction ni de destruction de l'objet.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets. J'ai du mal à donner des arguments contre la forme 1 (au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée par les avantages offerts.
-- -Stan
Franck Branjonneau
"David F." écrivait:
1. int fct( const INT& n ); 2. int fct ( INT n );
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Tu mélanges constance et passage par valeur ou par référence. Si n est constant dans le corps de la fonction alors tu utilises 1 ou 3. int fct(INT const n);
Sinon tu utilises 2 ou 4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros). -- Franck Branjonneau
"David F." <dfleury2@libertysurf.fr> écrivait:
1. int fct( const INT& n );
2. int fct ( INT n );
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1.
pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Tu mélanges constance et passage par valeur ou par référence. Si n est
constant dans le corps de la fonction alors tu utilises 1 ou
3. int fct(INT const n);
Sinon tu utilises 2 ou
4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le
typage dynamique ou si l'objet est gros (pour une définition ad hoc de
gros).
--
Franck Branjonneau <fasbjx@free.fr>
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Tu mélanges constance et passage par valeur ou par référence. Si n est constant dans le corps de la fonction alors tu utilises 1 ou 3. int fct(INT const n);
Sinon tu utilises 2 ou 4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros). -- Franck Branjonneau
Vincent Lascaux
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
Est ce que le compilateur a le droit de modifier un passage par référence const en un passage par valeur ? En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne raison de faire ca serait que foo est une fonction template, qu'on a écrit const T& parceque T peut être très lourd à copier, et qu'on utilise foo<int>), est ce que le compilo est en droit d'utiliser la premiere version ? Est ce qu'en pratique les compilos le font ?
-- Vincent
Tu utilises le passage par référence si tu en as besoin pour le
typage dynamique ou si l'objet est gros (pour une définition ad hoc de
gros).
Est ce que le compilateur a le droit de modifier un passage par référence
const en un passage par valeur ?
En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne raison de faire ca
serait que foo est une fonction template, qu'on a écrit const T& parceque T
peut être très lourd à copier, et qu'on utilise foo<int>), est ce que le
compilo est en droit d'utiliser la premiere version ? Est ce qu'en pratique
les compilos le font ?
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
Est ce que le compilateur a le droit de modifier un passage par référence const en un passage par valeur ? En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne raison de faire ca serait que foo est une fonction template, qu'on a écrit const T& parceque T peut être très lourd à copier, et qu'on utilise foo<int>), est ce que le compilo est en droit d'utiliser la premiere version ? Est ce qu'en pratique les compilos le font ?
-- Vincent
David F.
----- Original Message ----- From: "David F."
Bonjour, je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens): - elle force la vérification que n ne sera pas modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n ( plus génant pour un vrai objet)
Plus génant ? Au contraire passer un objet par référence offre un gain : pas de construction ni de destruction de l'objet.
Quand je disais "( plus génant pour un vrai objet)" je parlais de la recopie.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets. J'ai du mal à donner des arguments contre la forme 1 (au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée par les avantages offerts.
-- -Stan
----- Original Message -----
From: "David F." <dfleury2@libertysurf.fr>
Bonjour,
je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens):
- elle force la vérification que n ne sera pas
modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n
( plus génant pour un vrai objet)
Plus génant ?
Au contraire passer un objet par référence offre un gain :
pas de construction ni de destruction de l'objet.
Quand je disais "( plus génant pour un vrai objet)"
je parlais de la recopie.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet
complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première
forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1.
pour les objets. J'ai du mal à donner des arguments contre la forme 1
(au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée
par les avantages offerts.
Bonjour, je lis parfois le code suivant (un poste récent le montre d'ailleurs):
1. int fct( const INT& n );
au lieu d'un simple
2. int fct ( INT n );
L'argument pour la forme 1. est (à mon sens): - elle force la vérification que n ne sera pas modifiée à l'intérieur de fct.
Oui.
- elle force un passage sans recopie de n ( plus génant pour un vrai objet)
Plus génant ? Au contraire passer un objet par référence offre un gain : pas de construction ni de destruction de l'objet.
Quand je disais "( plus génant pour un vrai objet)" je parlais de la recopie.
- elle évité d'avoir à réfléchir si INT est un POD ou un objet complexe et hésiter entre la forme 1. et 2.
Il n'y a pas a hésiter puisque la première forme est préférable ( sauf pour les types de base comme int ou double ).
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets. J'ai du mal à donner des arguments contre la forme 1 (au delà de la lourdeur de la notation).
La "lourdeur de la notation" est largement compensée par les avantages offerts.
-- -Stan
David F.
"David F." écrivait:
1. int fct( const INT& n ); 2. int fct ( INT n );
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Oui erreur de terme désolé, je voulais parler des types fondamentaux ou primitifs ( int, float, double, ... ).
Tu mélanges constance et passage par valeur ou par référence. Si n est constant dans le corps de la fonction alors tu utilises 1 ou 3. int fct(INT const n);
Je ne pense pas mélanger. La forme 3 n'a pas l'avantage (événtuel) de ne passer qu'un pointeur lors de l'appel de la fonction, ni d'éviter une recopie pour les instances d'objets complexes. (en plus d'être ignoré ou au pire signalé en warning car inutile)
Sinon tu utilises 2 ou 4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
En fait, ça je le sais déjà. Ce n'était pas tout à fait le sens de ma question. Je n'arriverais décidément jamais à me faire comprendre par écrit :(
Je retente ma chance avec une source externe. Le sujet tourne autour du point 25 de "C++ Coding Standards" Je traduis (enfin j'essaye) un cours etrait:
"Pour les paramètres en entrée seulement: - toujours "const" qualifier les pointeurs ou références qui ne seront pas modifiés - préférer la copie pour les types primitives et ceux à faible coût de copie ( Point, complex<float>, ... ) -> forme 2 - conséder le passage par valeur au lieu du passage par référence si la fonction nécessite une copie de cet argument. (équivalent à const + référence + création de la variable temporaire). -> disons forme 2'
Pour les paramètres en sortie ou entrée/sortie: - préférer les pointeurs pour les arguments optionnels, ou sauvegarde une copie du pointeur, ou manipule le responsable du pointé. - préférer une référence pour les arguments obligatoires (non soumis aux points précédents)"
(Merci à Sutter et Alexandrescu)
Mon problème (et uniquement celui là) est que j'ai du mal à justifié la forme 2 ou la forme 2' par rapport à la solution tout "const &" J'espère que c'est plus clair malgré ma traduction maladroite (le mieux c'est d'avoir l'original sous les yeux, ou même la version française qui est sortie ;) )
"David F." <dfleury2@libertysurf.fr> écrivait:
1. int fct( const INT& n );
2. int fct ( INT n );
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1.
pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Oui erreur de terme désolé, je voulais parler des types
fondamentaux ou primitifs ( int, float, double, ... ).
Tu mélanges constance et passage par valeur ou par référence. Si n est
constant dans le corps de la fonction alors tu utilises 1 ou
3. int fct(INT const n);
Je ne pense pas mélanger.
La forme 3 n'a pas l'avantage (événtuel) de ne passer qu'un
pointeur lors de l'appel de la fonction, ni d'éviter une recopie
pour les instances d'objets complexes.
(en plus d'être ignoré ou au pire signalé en warning car inutile)
Sinon tu utilises 2 ou
4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le
typage dynamique ou si l'objet est gros (pour une définition ad hoc de
gros).
En fait, ça je le sais déjà.
Ce n'était pas tout à fait le sens de ma question.
Je n'arriverais décidément jamais à me faire comprendre
par écrit :(
Je retente ma chance avec une source externe.
Le sujet tourne autour du point 25 de "C++ Coding Standards"
Je traduis (enfin j'essaye) un cours etrait:
"Pour les paramètres en entrée seulement:
- toujours "const" qualifier les pointeurs ou références qui
ne seront pas modifiés
- préférer la copie pour les types primitives et ceux à faible
coût de copie ( Point, complex<float>, ... ) -> forme 2
- conséder le passage par valeur au lieu du passage par référence
si la fonction nécessite une copie de cet argument.
(équivalent à const + référence + création de la variable temporaire).
-> disons forme 2'
Pour les paramètres en sortie ou entrée/sortie:
- préférer les pointeurs pour les arguments optionnels, ou sauvegarde
une copie du pointeur, ou manipule le responsable du pointé.
- préférer une référence pour les arguments obligatoires (non soumis
aux points précédents)"
(Merci à Sutter et Alexandrescu)
Mon problème (et uniquement celui là) est que j'ai du mal
à justifié la forme 2 ou la forme 2' par rapport à la solution
tout "const &"
J'espère que c'est plus clair malgré ma traduction maladroite
(le mieux c'est d'avoir l'original sous les yeux, ou même la version
française qui est sortie ;) )
Honnêtement, même si j'utilise la forme 2. pour les POD, et la 1. pour les objets.
Un POD est un objet -- enfin une instance d'un type POD est un objet...
Oui erreur de terme désolé, je voulais parler des types fondamentaux ou primitifs ( int, float, double, ... ).
Tu mélanges constance et passage par valeur ou par référence. Si n est constant dans le corps de la fonction alors tu utilises 1 ou 3. int fct(INT const n);
Je ne pense pas mélanger. La forme 3 n'a pas l'avantage (événtuel) de ne passer qu'un pointeur lors de l'appel de la fonction, ni d'éviter une recopie pour les instances d'objets complexes. (en plus d'être ignoré ou au pire signalé en warning car inutile)
Sinon tu utilises 2 ou 4. int fonc(INT& n);
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
En fait, ça je le sais déjà. Ce n'était pas tout à fait le sens de ma question. Je n'arriverais décidément jamais à me faire comprendre par écrit :(
Je retente ma chance avec une source externe. Le sujet tourne autour du point 25 de "C++ Coding Standards" Je traduis (enfin j'essaye) un cours etrait:
"Pour les paramètres en entrée seulement: - toujours "const" qualifier les pointeurs ou références qui ne seront pas modifiés - préférer la copie pour les types primitives et ceux à faible coût de copie ( Point, complex<float>, ... ) -> forme 2 - conséder le passage par valeur au lieu du passage par référence si la fonction nécessite une copie de cet argument. (équivalent à const + référence + création de la variable temporaire). -> disons forme 2'
Pour les paramètres en sortie ou entrée/sortie: - préférer les pointeurs pour les arguments optionnels, ou sauvegarde une copie du pointeur, ou manipule le responsable du pointé. - préférer une référence pour les arguments obligatoires (non soumis aux points précédents)"
(Merci à Sutter et Alexandrescu)
Mon problème (et uniquement celui là) est que j'ai du mal à justifié la forme 2 ou la forme 2' par rapport à la solution tout "const &" J'espère que c'est plus clair malgré ma traduction maladroite (le mieux c'est d'avoir l'original sous les yeux, ou même la version française qui est sortie ;) )
James Kanze
Vincent Lascaux wrote:
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
Est ce que le compilateur a le droit de modifier un passage par référence const en un passage par valeur ?
Le compilateur a droit à faire tout ce qui ne modifie pas le comportement visible du programme. S'il peut déterminer que le résultat en est le même, il peut faire la modification.
En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne raison de faire ca serait que foo est une fonction template, qu'on a écrit const T& parceque T peut être très lourd à copier, et qu'on utilise foo<int>), est ce que le compilo est en droit d'utiliser la premiere version ?
Oui, à condition que ça ne modifie pas le comportement visible (d'un programme légal).
À peu près la seule façon que ça pourrait modifier le comportement visible, c'est si la fonction faisait un const_cast, et modifiait en fait le paramètre. À partir de ce moment, en revanche, l'appel de la fonction avec un objet const ou avec un rvalue menerait à un comportement indéfini.
Est ce qu'en pratique les compilos le font ?
Sauf dans le cas des fonctions inline, je crois que cette optimisation doit être extrèmement rare. Dans la pratique, les compilateurs utilisent la même forme de l'appel partout. Il faudrait donc où que le compilateur sache à chaque endroit d'un appel qu'il n'y a pas de const_cast dans la fonction, soit que le compilateur puisse voir un appel avec un rvalue ou un objet const, et savoir qu'il puisse en voir un à chaque endroit de l'appel.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Vincent Lascaux wrote:
Tu utilises le passage par référence si tu en as besoin pour
le typage dynamique ou si l'objet est gros (pour une
définition ad hoc de gros).
Est ce que le compilateur a le droit de modifier un passage
par référence const en un passage par valeur ?
Le compilateur a droit à faire tout ce qui ne modifie pas le
comportement visible du programme. S'il peut déterminer que le
résultat en est le même, il peut faire la modification.
En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne
raison de faire ca serait que foo est une fonction template,
qu'on a écrit const T& parceque T peut être très lourd à
copier, et qu'on utilise foo<int>), est ce que le compilo est
en droit d'utiliser la premiere version ?
Oui, à condition que ça ne modifie pas le comportement visible
(d'un programme légal).
À peu près la seule façon que ça pourrait modifier le
comportement visible, c'est si la fonction faisait un
const_cast, et modifiait en fait le paramètre. À partir de ce
moment, en revanche, l'appel de la fonction avec un objet const
ou avec un rvalue menerait à un comportement indéfini.
Est ce qu'en pratique les compilos le font ?
Sauf dans le cas des fonctions inline, je crois que cette
optimisation doit être extrèmement rare. Dans la pratique, les
compilateurs utilisent la même forme de l'appel partout. Il
faudrait donc où que le compilateur sache à chaque endroit d'un
appel qu'il n'y a pas de const_cast dans la fonction, soit que
le compilateur puisse voir un appel avec un rvalue ou un objet
const, et savoir qu'il puisse en voir un à chaque endroit de
l'appel.
--
James Kanze mailto: james.kanze@free.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Tu utilises le passage par référence si tu en as besoin pour le typage dynamique ou si l'objet est gros (pour une définition ad hoc de gros).
Est ce que le compilateur a le droit de modifier un passage par référence const en un passage par valeur ?
Le compilateur a droit à faire tout ce qui ne modifie pas le comportement visible du programme. S'il peut déterminer que le résultat en est le même, il peut faire la modification.
En gros, si c'est plus rapide d'appeler
int foo(int i) { return i+1; }
que
int foo(const int& i) { return i+1; }
mais qu'on écrit quand même la deuxième forme (une bonne raison de faire ca serait que foo est une fonction template, qu'on a écrit const T& parceque T peut être très lourd à copier, et qu'on utilise foo<int>), est ce que le compilo est en droit d'utiliser la premiere version ?
Oui, à condition que ça ne modifie pas le comportement visible (d'un programme légal).
À peu près la seule façon que ça pourrait modifier le comportement visible, c'est si la fonction faisait un const_cast, et modifiait en fait le paramètre. À partir de ce moment, en revanche, l'appel de la fonction avec un objet const ou avec un rvalue menerait à un comportement indéfini.
Est ce qu'en pratique les compilos le font ?
Sauf dans le cas des fonctions inline, je crois que cette optimisation doit être extrèmement rare. Dans la pratique, les compilateurs utilisent la même forme de l'appel partout. Il faudrait donc où que le compilateur sache à chaque endroit d'un appel qu'il n'y a pas de const_cast dans la fonction, soit que le compilateur puisse voir un appel avec un rvalue ou un objet const, et savoir qu'il puisse en voir un à chaque endroit de l'appel.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Franck Branjonneau
"David F." écrivait:
- préférer la copie pour les types primitives et ceux à faible coût de copie ( Point, complex<float>, ... ) -> forme 2 - conséder le passage par valeur au lieu du passage par référence si la fonction nécessite une copie de cet argument. (équivalent à const + référence + création de la variable temporaire). -> disons forme 2'
Mon problème (et uniquement celui là) est que j'ai du mal à justifié la forme 2 ou la forme 2' par rapport à la solution tout "const &"
Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori, plus d'opportunités au compilateur de générer du code plus efficient.
Pour la forme 2' c'est une question de responsabilité. Si j'ai
struct S { S(const &) { throw "anything"; } };
int main() { S s; foo(s); }
Que se passe-t-il avec
void foo(S const & p) { S s(p); }
et avec
void foo(S p) { }
? -- Franck Branjonneau
"David F." <dfleury2@libertysurf.fr> écrivait:
- préférer la copie pour les types primitives et ceux à faible
coût de copie ( Point, complex<float>, ... ) -> forme 2
- conséder le passage par valeur au lieu du passage par référence
si la fonction nécessite une copie de cet argument.
(équivalent à const + référence + création de la variable temporaire).
-> disons forme 2'
Mon problème (et uniquement celui là) est que j'ai du mal
à justifié la forme 2 ou la forme 2' par rapport à la solution
tout "const &"
Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori,
plus d'opportunités au compilateur de générer du code plus efficient.
Pour la forme 2' c'est une question de responsabilité. Si j'ai
- préférer la copie pour les types primitives et ceux à faible coût de copie ( Point, complex<float>, ... ) -> forme 2 - conséder le passage par valeur au lieu du passage par référence si la fonction nécessite une copie de cet argument. (équivalent à const + référence + création de la variable temporaire). -> disons forme 2'
Mon problème (et uniquement celui là) est que j'ai du mal à justifié la forme 2 ou la forme 2' par rapport à la solution tout "const &"
Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori, plus d'opportunités au compilateur de générer du code plus efficient.
Pour la forme 2' c'est une question de responsabilité. Si j'ai
struct S { S(const &) { throw "anything"; } };
int main() { S s; foo(s); }
Que se passe-t-il avec
void foo(S const & p) { S s(p); }
et avec
void foo(S p) { }
? -- Franck Branjonneau
Franck Branjonneau
"David F." écrivait:
Pour la forme 2' c'est une question de responsabilité. Si j'ai struct S {
s() {}
S(const &) { throw "anything"; } }; int main() { S s; foo(s); } Que se passe-t-il avec void foo(S const & p) { S s(p); } et avec void foo(S p) { } ?
Je dirai que ça throw pour les deux.
Oui mais dans le premier cas c'est l'appelé qui lance l'exception alors que dans le second cas c'est l'appelant.
un exemple d'utilisation de la forme 2' pourrait être une fonction trim ne modifiant par l'argument.
Ici, c'est le cas 1. Tu choisis le passage par valeur. -- Franck Branjonneau
Franck Branjonneau
"David F." écrivait:
Ca ne m'aide pas vraiment pour justifier l'emploi de l'une ou l'autre des "formes".
void SetSomeBoolFlag( bool theFlag ); ou void SetSomeBoolFlag( const bool& theFlag ); // ou void SetSomeBoolFlag( bool const & theFlag ); Ici, c'est le cas 1. Tu choisis le passage par valeur.
Oui, mais pourquoi ?
Message-ID: Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori, plus d'opportunités au compilateur de générer du code plus efficient. -- Franck Branjonneau
"David F." <dfleury2@libertysurf.fr> écrivait:
Ca ne m'aide pas vraiment pour justifier l'emploi de l'une
ou l'autre des "formes".
void SetSomeBoolFlag( bool theFlag );
ou
void SetSomeBoolFlag( const bool& theFlag );
// ou void SetSomeBoolFlag( bool const & theFlag );
Ici, c'est le cas 1. Tu choisis le passage par valeur.
Oui, mais pourquoi ?
Message-ID: <87oe5p9v90.fsf@alpha.tchume.net>
Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori,
plus d'opportunités au compilateur de générer du code plus efficient.
--
Franck Branjonneau <fasbjx@free.fr>
Ca ne m'aide pas vraiment pour justifier l'emploi de l'une ou l'autre des "formes".
void SetSomeBoolFlag( bool theFlag ); ou void SetSomeBoolFlag( const bool& theFlag ); // ou void SetSomeBoolFlag( bool const & theFlag ); Ici, c'est le cas 1. Tu choisis le passage par valeur.
Oui, mais pourquoi ?
Message-ID: Pour la forme 2 c'est parce que utiliser des valeurs laisse, à priori, plus d'opportunités au compilateur de générer du code plus efficient. -- Franck Branjonneau
Franck Branjonneau
"Vincent Lascaux" écrivait:
"Franck Branjonneau" a écrit dans le message de news:
"David F." écrivait:
Pour la forme 2' c'est une question de responsabilité. Si j'ai struct S {
Je dirai que ça throw pour les deux.
Oui mais dans le premier cas c'est l'appelé qui lance l'exception alors que dans le second cas c'est l'appelant.
Est ce qu'on peut être sur de ca ?
Oui.
Le compilo n'est il pas en droit d'inliner ?
Message-ID: <4351803f$0$21699$ Le compilateur a droit à faire tout ce qui ne modifie pas le comportement visible du programme. S'il peut déterminer que le résultat en est le même, il peut faire la modification.
Essaie
void foo(S const p) { std::cout << "In foon"; } void foo(S const & p) { std::cout << "In foon"; S s(p); }
pour t'en persuader. -- Franck Branjonneau
"Vincent Lascaux" <nospam@nospam.org> écrivait:
"Franck Branjonneau" <fasbjx@free.fr> a écrit dans le message de news:
87slv1hyzl.fsf@alpha.tchume.net...
"David F." <dfleury2@libertysurf.fr> écrivait:
Pour la forme 2' c'est une question de responsabilité. Si j'ai
struct S {
Je dirai que ça throw pour les deux.
Oui mais dans le premier cas c'est l'appelé qui lance l'exception alors
que dans le second cas c'est l'appelant.
Est ce qu'on peut être sur de ca ?
Oui.
Le compilo n'est il pas en droit d'inliner ?
Message-ID: <4351803f$0$21699$626a54ce@news.free.fr>
Le compilateur a droit à faire tout ce qui ne modifie pas le
comportement visible du programme. S'il peut déterminer que le
résultat en est le même, il peut faire la modification.
Essaie
void foo(S const p) { std::cout << "In foon"; }
void foo(S const & p) { std::cout << "In foon"; S s(p); }
pour t'en persuader.
--
Franck Branjonneau <fasbjx@free.fr>
"Franck Branjonneau" a écrit dans le message de news:
"David F." écrivait:
Pour la forme 2' c'est une question de responsabilité. Si j'ai struct S {
Je dirai que ça throw pour les deux.
Oui mais dans le premier cas c'est l'appelé qui lance l'exception alors que dans le second cas c'est l'appelant.
Est ce qu'on peut être sur de ca ?
Oui.
Le compilo n'est il pas en droit d'inliner ?
Message-ID: <4351803f$0$21699$ Le compilateur a droit à faire tout ce qui ne modifie pas le comportement visible du programme. S'il peut déterminer que le résultat en est le même, il peut faire la modification.
Essaie
void foo(S const p) { std::cout << "In foon"; } void foo(S const & p) { std::cout << "In foon"; S s(p); }