Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1497 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  void f(int val) vs void f(int & val)

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

void f(int val) vs void f(int & val)

n°1937854
Glock 17Pr​o
Posté le 04-11-2009 à 23:20:38  profilanswer
 

salut,
 
en terme de perf le fait de passer des types de base par référence est-il plus lent que de les passer par valeur ou cela revient il exactement au même ?
 
merci


---------------
.
mood
Publicité
Posté le 04-11-2009 à 23:20:38  profilanswer
 

n°1937878
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 06:54:02  profilanswer
 

par référence ou par référence constante. La ton exemple est foireux car la sémantique de la fonction change.

n°1937881
Glock 17Pr​o
Posté le 05-11-2009 à 07:40:37  profilanswer
 

disons les deux cas, par rapport à un passage par référence et par rapport à un passage par référence constante


---------------
.
n°1937962
bjone
Insert booze to continue
Posté le 05-11-2009 à 12:54:01  profilanswer
 

Si ce que tu veux comme cas d'utilisation, c'est du void f(int val), le passage par valeur sera plus économique.
 

Maintenant je dirais (probablement mal):
A partir du moment où tu as une référence, la logique voudrait que le compilo déréférence la référence a chaque utilisation car l'objet référencé peut avoir changé (bon à voir peut être avec volatile).
 
void f(int val)
{
  while (val)
  {
     poulpe();
     --val;
  }
}
 
void f(int &val)
{
  while (val)
  {
     poulpe(); // poulpe peut avoir changé le int  
     --val;
  }
}
 
Maintenant je sais pas si c'est une remarque à la con. (et que le compilo n'optimisera pas que si y'a un volatile en plus :D)

edit: je me suis pris les pieds dans le tapis en voulant faire une démo foireuse >> seek coffee.
 
Mais si tu cherche les perfs, à partir du moment où le type rentre dans un registre du cpu (ou plusieurs de manière efficace) c'est int ou const int (le const permettant entre autre au niveau optimisation de garantir que l'appelé ne modifia pas le registre utilisé pour le passage).
 
Enfin je dis ça comme ça moa.


Message édité par bjone le 05-11-2009 à 13:11:02
n°1937967
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 13:18:14  profilanswer
 

gcc à l'air de pas tenir compte des const& sur les types atomiques.

n°1938029
Un Program​meur
Posté le 05-11-2009 à 15:24:53  profilanswer
 

Joel F a écrit :

gcc à l'air de pas tenir compte des const& sur les types atomiques.


 
Il donne pourtant le resultat que j'attends pour

Code :
  1. #include <iostream>
  2. #include <ostream>
  3. int i = 0;
  4. void f(int const& p)
  5. {
  6.     std::cout << "p = " << p << '\n';
  7.     i = 42;
  8.     std::cout << "p = " << p << '\n';
  9. }
  10. int main()
  11. {
  12.     f(i);
  13.     return 0;
  14. }



---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938043
bjone
Insert booze to continue
Posté le 05-11-2009 à 16:09:29  profilanswer
 

il voulait dire const int & nope ?
oupa ?
ha non café :D


Message édité par bjone le 05-11-2009 à 17:15:10
n°1938087
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 17:45:38  profilanswer
 

Un Programmeur a écrit :


Il donne pourtant le resultat que j'attends pour


 
je veut dire que le code généré pour f(int) et f(int cosnt& ) est identique ...

n°1938118
Un Program​meur
Posté le 05-11-2009 à 19:28:14  profilanswer
 

C'est bien ce que j'avais compris.  Je vois mal comment c'est possible si on veut traiter correctement le genre de cas que j'ai donné (hormis si f est statique et qu'on ne passe jamais de pointeurs à f à une fonction dont on ne voit pas le code et tous les appels...).


---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938125
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 19:43:16  profilanswer
 

Un Programmeur a écrit :

C'est bien ce que j'avais compris.  Je vois mal comment c'est possible si on veut traiter correctement le genre de cas que j'ai donné (hormis si f est statique et qu'on ne passe jamais de pointeurs à f à une fonction dont on ne voit pas le code et tous les appels...).


 
Hmmmm, soit y a inference de l'origine de la référence soit ca a changé.
Je comprends pas pourquoi j'ai le résultat p=0,p=42 d'ailleurs au vu du code.

mood
Publicité
Posté le 05-11-2009 à 19:43:16  profilanswer
 

n°1938128
Un Program​meur
Posté le 05-11-2009 à 19:50:49  profilanswer
 

C'est pourtant le comportement attendu.  Une référence est un alias pour l'objet initial (ici i), le fait qu'on ne puisse pas modifier l'objet en utilisant cet alias n'empêche pas de pouvoir le faire en utilisant un autre accès.
 
Et si tu parles du code généré, ça me semble compréhensible ici -- g++ 4.2 sur x86.  En gros c'est compilé comme

Code :
  1. #include <iostream>
  2. #include <ostream>
  3. int i = 0;
  4. void f(int const* p)
  5. {
  6.     std::cout << "p = " << *p << '\n';
  7.     i = 42;
  8.     std::cout << "p = " << *p << '\n';
  9. }
  10. int main()
  11. {
  12.     f(&i);
  13.     return 0;
  14. }


---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938130
bjone
Insert booze to continue
Posté le 05-11-2009 à 19:59:25  profilanswer
 

Code asm il voulait dire je pense :??:

n°1938131
Un Program​meur
Posté le 05-11-2009 à 20:12:43  profilanswer
 

Et bien?

 

Appel de f dans main:

Code :
  1. .LCFI17:
  2. sub %esp, 4
  3. .LCFI18:
  4. mov DWORD PTR [%esp], OFFSET FLAT:i
  5. call f(int const& )
  6. add %esp, 4


on passe l'adresse de i.  Code de f

Code :
  1. .text
  2. .align 2
  3. .p2align 4,,15
  4. .globl f(int const& )
  5. .type f(int const& ), @function
  6. f(int const& ):
  7. .LFB1428:
  8. push %ebp
  9. .LCFI7:
  10. mov %ebp, %esp
  11. .LCFI8:
  12. sub %esp, 40
  13. .LCFI9:
  14. mov DWORD PTR [%ebp-4], %edi
  15. .LCFI10:
  16. mov %edi, DWORD PTR [%ebp+8]
  17. mov DWORD PTR [%ebp-8], %esi
  18. .LCFI11:
  19. lea %esi, [%ebp-13]
  20. mov DWORD PTR [%ebp-12], %ebx
  21. .LCFI12:
  22. mov %ebx, DWORD PTR [%edi]
  23. mov DWORD PTR [%esp+8], 4
  24. mov DWORD PTR [%esp+4], OFFSET FLAT:.LC0
  25. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  26. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  27. mov DWORD PTR [%esp+4], %ebx
  28. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  29. call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  30. mov DWORD PTR [%esp+4], %esi
  31. mov BYTE PTR [%ebp-13], 10
  32. mov DWORD PTR [%esp+8], 1
  33. mov DWORD PTR [%esp], %eax
  34. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  35. mov DWORD PTR i, 42
  36. mov %ebx, DWORD PTR [%edi]
  37. mov DWORD PTR [%esp+8], 4
  38. mov DWORD PTR [%esp+4], OFFSET FLAT:.LC0
  39. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  40. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  41. mov DWORD PTR [%esp+4], %ebx
  42. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  43. call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  44. mov DWORD PTR [%esp+4], %esi
  45. mov BYTE PTR [%ebp-13], 10
  46. mov DWORD PTR [%esp+8], 1
  47. mov DWORD PTR [%esp], %eax
  48. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  49. mov %ebx, DWORD PTR [%ebp-12]
  50. mov %esi, DWORD PTR [%ebp-8]
  51. mov %edi, DWORD PTR [%ebp-4]
  52. mov %esp, %ebp
  53. pop %ebp
  54. ret


On voit bien qu'on déréférence ce qui est passé (DWORD PTR[%edi]).

 

(g++ -O2 -masm=intel -S puis le résultat est passé dans c++filt pour démangler les noms)


Message édité par Un Programmeur le 05-11-2009 à 20:15:04

---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938134
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 20:22:38  profilanswer
 

je viens de vérifier. Je m'a fait eu comme une tanche donc.

n°1938140
Glock 17Pr​o
Posté le 05-11-2009 à 21:06:21  profilanswer
 

bon in finé c'est quoi le verdict en terme de perf :$


---------------
.
n°1938147
Un Program​meur
Posté le 05-11-2009 à 21:22:14  profilanswer
 

J'ai du mal à comprendre pourquoi tu veux comparer par valeur et par référence non constante, le choix entre les deux doit se faire à mon avis sur des considérations sémantiques.
 
Entre par valeur et par référence constante et si on a le choix -- autrement dit, si les considérations de possibilité d'alias n'impose pas l'un ou l'autre -- par valeur devrait généralement être plus performant (mais comme toujours 1/ est-ce que ce n'est pas prématuré d'envisager ce genre de chose 2/ mesure 3/ est-ce que le gain vaut la peine)


---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938149
Joel F
Real men use unique_ptr
Posté le 05-11-2009 à 21:23:44  profilanswer
 

et surtout paye ta micro-optimisation qui sert à rien 99% du temps

n°1938152
Glock 17Pr​o
Posté le 05-11-2009 à 21:32:58  profilanswer
 

pour mesurer sous visual, vous utilisez quoi  typiquement ? je me heurte à ce problème , QueryCouter & co ? et si oui de quelle manière le faite vous


---------------
.
n°1938161
Glock 17Pr​o
Posté le 05-11-2009 à 22:17:27  profilanswer
 

no idea ?


---------------
.
n°1938164
bjone
Insert booze to continue
Posté le 05-11-2009 à 22:40:59  profilanswer
 

Tu veux mesurer quoi ? Une différence entre passage par référence et passage par valeur ?

n°1938165
Glock 17Pr​o
Posté le 05-11-2009 à 22:44:29  profilanswer
 

exact


---------------
.
n°1938192
bjone
Insert booze to continue
Posté le 06-11-2009 à 00:57:05  profilanswer
 

Tu va mesurer du bruit :D
 
Quand c'est une implémentation d'un algo avec une charge de travail réaliste, les queryperfcounters & autres sont corrects.
 
Mais pour ce genre de trucs faudrait du rdtsc.
 
Dans tous les cas c'est de l'enculage de mouche, d'autant plus que la donne peut changer si le compilo peut faire de l'inlining sauvage ou de la compilation lors de l'édition des liens, ou pas (link dll/lib statique).
 
Comme dit plus haut, le code tu le fais de la manière la plus élégante possible et la plus cohérente avec l'intention initiale, et autrement pour un type qui tiens dans un ou deux registre => valeur, classe/struct => ref.


Message édité par bjone le 09-11-2009 à 16:55:21
n°1938631
Glock 17Pr​o
Posté le 07-11-2009 à 14:59:01  profilanswer
 

ok ok donc au final ça revient au même alors


---------------
.
n°1938711
Un Program​meur
Posté le 08-11-2009 à 10:24:39  profilanswer
 

A lire avant de chercher a optimiser http://www.linux-kongress.org/2009 [...] eitner.pdf


---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°1938712
Joel F
Real men use unique_ptr
Posté le 08-11-2009 à 10:35:40  profilanswer
 

/me bookmark this

n°1938757
Glock 17Pr​o
Posté le 08-11-2009 à 17:13:58  profilanswer
 

thanks pour le lien


---------------
.
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  void f(int val) vs void f(int & val)

 

Sujets relatifs
interet fonction voidStopper public void (pour gestion d'événements)
[JAVA] Méthode "void" ou faire un "return"[DDD] et le type void
Typage d'un pointeur "void *"argument void *
voidExecution d'un void main(args[]) en java et valeur retour
[C] -pedantic et affectation entre pointeur de fonction et "void *"de char** à void**
Plus de sujets relatifs à : void f(int val) vs void f(int & val)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR