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

  FORUM HardWare.fr
  Programmation
  C++

  besoin de testeurs: retour de fonction

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

besoin de testeurs: retour de fonction

n°468221
Taz
bisounours-codeur
Posté le 25-07-2003 à 23:55:01  profilanswer
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. class Foo
  4. {
  5. public:
  6.   Foo()
  7.   {
  8.     cout << "Foo()\t"
  9.  << "this = " << this
  10.  << endl;
  11.   }
  12.   Foo(int i)
  13.   {
  14.     cout << "Foo(int)\t"
  15.  << "this = " << this
  16.  << endl;
  17.   }
  18.   Foo(const Foo &other)
  19.   {
  20.     cout << "Foo(Foo)\t"
  21.  << "this = " << this
  22.  << " other = " << &other
  23.  << endl;
  24.   }
  25.   ~Foo()
  26.   {
  27.     cout << "~Foo()\t"
  28.  << "this = " << this
  29.  << endl;
  30.   }
  31.   Foo& operator=(const Foo &other)
  32.   {
  33.     cout << "opertor=(Foo)\t"
  34.  << "this = " << this
  35.  << " other = " << &other
  36.  << endl;
  37.     return *this;
  38.   }
  39. };
  40. Foo f()
  41. {
  42.   cout << "\nf()\n";
  43.   return Foo();
  44. }
  45. Foo g()
  46. {
  47.   cout << "\ng()\n";
  48.   return Foo(42);
  49. }
  50. Foo h()
  51. {
  52.   cout << "\nh()\n";
  53.   Foo tmp;
  54.   return tmp;
  55. }
  56. int main()
  57. {
  58.   Foo res;
  59.   res=f();
  60.   res=g();
  61.   res=h();
  62. }


 
 
qui donne avec mon compilateur (g++ 3.3.1)
 

Foo()   this = 0xbffffc30
 
f()
Foo()   this = 0xbffffc20
opertor=(Foo)   this = 0xbffffc30 other = 0xbffffc20
~Foo()  this = 0xbffffc20
 
g()
Foo(int)        this = 0xbffffc20
opertor=(Foo)   this = 0xbffffc30 other = 0xbffffc20
~Foo()  this = 0xbffffc20
 
h()
Foo()   this = 0xbffffc20
opertor=(Foo)   this = 0xbffffc30 other = 0xbffffc20
~Foo()  this = 0xbffffc20
~Foo()  this = 0xbffffc30


Message édité par Taz le 25-07-2003 à 23:56:10
mood
Publicité
Posté le 25-07-2003 à 23:55:01  profilanswer
 

n°468225
bjone
Insert booze to continue
Posté le 25-07-2003 à 23:58:00  profilanswer
 

VC7 / Release:

Code :
  1. Foo()   this = 0012FED8
  2. f()
  3. Foo()   this = 0012FED7
  4. opertor=(Foo)   this = 0012FED8 other = 0012FED7
  5. ~Foo()  this = 0012FED7
  6. g()
  7. Foo(int)        this = 0012FED7
  8. opertor=(Foo)   this = 0012FED8 other = 0012FED7
  9. ~Foo()  this = 0012FED7
  10. h()
  11. Foo()   this = 0012FEB0
  12. Foo(Foo)        this = 0012FED7 other = 0012FEB0
  13. ~Foo()  this = 0012FEB0
  14. opertor=(Foo)   this = 0012FED8 other = 0012FED7
  15. ~Foo()  this = 0012FED7
  16. ~Foo()  this = 0012FED8
  17. Press any key to continue


 

n°468230
bjone
Insert booze to continue
Posté le 26-07-2003 à 00:01:08  profilanswer
 

fait une recopie en trop je regardes les options d'optimisation...

n°468231
Taz
bisounours-codeur
Posté le 26-07-2003 à 00:01:54  profilanswer
 

ouais y a un truc bizarre... voir ce topic http://forum.hardware.fr/forum2.ph [...] h=&subcat=
et les différentes traces...


Message édité par Taz le 26-07-2003 à 00:03:18
n°468240
Taz
bisounours-codeur
Posté le 26-07-2003 à 00:16:52  profilanswer
 

j'obtiens la meme trace que toi, c'est à dire pour h si je remplace
 
return tmp;
 
par  
 
return Foo(tmp);
 
 
je me renseigne sur ce comportement...
 
c'est interessant...

n°468251
bjone
Insert booze to continue
Posté le 26-07-2003 à 00:35:06  profilanswer
 

je viens de faire un test avec openwatcom:
 

Code :
  1. loading object files
  2. searching libraries
  3. creating a PMODE/W executable
  4. C:\Temp\rtetrert>t
  5. Foo()   this = 0x1cef8
  6. f()
  7. Foo()   this = 0x1cef4
  8. opertor=(Foo)   this = 0x1cef8 other = 0x1cef4
  9. ~Foo()  this = 0x1cef4
  10. g()
  11. Foo(int)        this = 0x1cef0
  12. opertor=(Foo)   this = 0x1cef8 other = 0x1cef0
  13. ~Foo()  this = 0x1cef0
  14. h()
  15. Foo()   this = 0x1ceec
  16. opertor=(Foo)   this = 0x1cef8 other = 0x1ceec
  17. ~Foo()  this = 0x1ceec
  18. ~Foo()  this = 0x1cef8

n°468254
bjone
Insert booze to continue
Posté le 26-07-2003 à 00:41:49  profilanswer
 

VC6 a le même comportement que VC7 (il y a une recopie de trop)

n°468257
Taz
bisounours-codeur
Posté le 26-07-2003 à 00:44:17  profilanswer
 

BJOne a écrit :

VC6 a le même comportement que VC7 (il y a une recopie de trop)

le tout est de savoir si c'est vraiment en trop. comme tu peux voir dans l'autre topic, c'est très pénalisant  :ouch:

n°468261
bjone
Insert booze to continue
Posté le 26-07-2003 à 00:47:23  profilanswer
 

bin ça casse un peu le truc à la base :/

n°468262
bjone
Insert booze to continue
Posté le 26-07-2003 à 00:47:41  profilanswer
 

j'ai pas borland c++ 6 d'installé :/

mood
Publicité
Posté le 26-07-2003 à 00:47:41  profilanswer
 

n°468266
Taz
bisounours-codeur
Posté le 26-07-2003 à 00:49:03  profilanswer
 

BJOne a écrit :

bin ça casse un peu le truc à la base :/

oui, et même pour une expression simple, ça fait un boulot considérable en plus!

n°468323
Taz
bisounours-codeur
Posté le 26-07-2003 à 10:40:58  profilanswer
 

la réponse de Jean Marc Bourget sur fclc++
Je suis d'accord avec lui, il s'agit d'une optimisation permise par la norme
 
 

Citation :

> je me pose des questions sur les retours de fonction et les copies
 
Il y a deux choses à considérer: le comportement logique et les
optimisations permises par la norme.
 
Le comportement logique c'est que le retour de fonction utilise le
constructeur de copie.
 
Les optimisations permises sont au nombres de deux:
 
   - en toute circonstance (donc pas uniquement au retour d'une
     fonction), quand un constructeur de copie devrait être appelé
     pour copier un temporaire, le compilateur peut utiliser le
     temporaire à la place (ou plus vraissemblablement contruire
     directement le temporaire)
 
   - lorsqu'on retourne un objet nommé d'une fonction, on peut
     utiliser l'objet plutôt que d'en faire une copie (NRVO) (ou plus
     vraissemblablement mettre l'objet nommé directement à l'endroit
     ou la valeur de retour de la fonction est attendu, donc même si
     la norme le permet, je doute qu'un compilateur utilise la NRVO
     quand dans des chemins différents on retourne des objets nommés
     différents sauf dans des cas particuliers -- voir ci-dessus)
 
> Foo f()
> {
>   cout << "\nf()\n";
>   return Foo();
> }
 
On retourne un temporaire:  
  construction du temporaire
  construction de la valeur retournée par copie du temporaire
    (peut être supprimée en construisant le temporaire directement en
     tant que valeur retournée)
donc 0 ou 1 copie
 
> Foo g()
> {
>   cout << "\ng()\n";
>   return Foo(42);
> }
 
Même chose
 
> Foo h()
> {
>   cout << "\nh()\n";
>   Foo tmp;
>   return tmp;
> }
 
On retourne une valeur nommée:
   construction de la valuer
   construction de la valeur retournée par copie de la valeur nommée
    (peut être supprimée en construisant la valeur nommée directement en
     tant que valeur retournée)
donc 0 ou 1 copie
 
> Foo i()
> {
>   cout << "\nh()\n";
>   Foo tmp;
>   return Foo(tmp);
> }
 
On retourne un temporaire construit à partir d'une valeur nommée.
   construction de la valeur nommée
   construction du temporaire par copie de la valeur nommée
   construction de la valeur retournée par copie du temporaire
    (peut être supprimée en construisant le temporaire directement en
     tant que valeur retournée)
donc 1 ou 2 copies
 
 
> donne sur mon systeme (linux, g++ 3.3.1)
 
On voit que g++ implémente les deux optimisations
 
> avec VC7, la trace de h() donne
>  
>  h()
>   Foo()   this = 0012FEB0
>   Foo(Foo)        this = 0012FED7 other = 0012FEB0 ~Foo()  this = 0012FEB0
>   opertor=(Foo)   this = 0012FED8 other = 0012FED7 ~Foo()  this = 0012FED7
>   ~Foo()  this = 0012FED8
 
et que VC7 n'a pas le NRVO
 
A propos de ma remarque sur les objets différents, dans ce cas
 
Foo nrvo(bool b) {
  if (b) {
    Foo res1;
    return res1;
  } else {
    Foo res2;
    return res2;
  }
}
 
rien n'empèche l'application du nrvo (on retourne des objets
différents mais il n'y a pas de problème de destruction car l'autre
objet ne doit pas être détruit), pourtant ni gcc 3.3 ni como ne le
font pas alors qu'ils le font pour
 
Foo nrvo(bool b) {
  Foo res1;
  if (b) {
    return res1;
  } else {
    return res1;
  }
}

n°514966
bjone
Insert booze to continue
Posté le 15-09-2003 à 15:14:11  profilanswer
 

Sinon je viens de tester avec VS.NET 2003, le constructeur de recopie en trop y est aussi, avec le compilo Intel C++ 7 c'est bon.

n°514978
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 15:29:20  profilanswer
 

BJOne a écrit :

j'ai pas borland c++ 6 d'installé :/


 
moi je l'ai :
 


Foo()   this = 1245060
 
f()
Foo()   this = 1245052
opertor=(Foo)   this = 1245060 other = 1245052
~Foo()  this = 1245052
 
g()
Foo(int)        this = 1245044
opertor=(Foo)   this = 1245060 other = 1245044
~Foo()  this = 1245044
 
h()
Foo()   this = 1244968
Foo(Foo)        this = 1245036 other = 1244968
~Foo()  this = 1244968
opertor=(Foo)   this = 1245060 other = 1245036
~Foo()  this = 1245036
~Foo()  this = 1245060


Message édité par antp le 15-09-2003 à 15:30:12

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°514979
gatorette
Posté le 15-09-2003 à 15:30:05  profilanswer
 

Le comportement est appelé "return value optimization" et il y a déjà pas mal de discussions sur le sujet ici. L'article le plus complet sur le sujet (et qui relève les contradictions à ce sujet dans l'ARM !) est celui-ci.
 
Le problème est de savoir si le compilateur peut effectivement se passer de la recopie. Pour cela il faut qu'aucun constructeur n'ait d'effet de bord.
 
Par exemple :

Code :
  1. class Foo
  2. {
  3. public:
  4. Foo() { ++numInstances_; }
  5. Foo( const Foo& f ) { ++numInstances_; }
  6. private:
  7. static int numInstances_;
  8. };
  9. int Foo::numInstances_ = 0;
  10. Foo f()
  11. {
  12. Foo f;
  13. /* ... */
  14. return f;
  15. }


 
Ici, il est nécessaire de ne pas faire l'optimisation. En effet, il y a réellement la création d'un objet Foo et ensuite sa recopie. Or à cause de la variable statique, l'appel aux deux constructeurs est obligatoire.
Par contre, si la variable statique numInstances_ n'existait pas, l'optimisation serait justifiée.


Message édité par gatorette le 15-09-2003 à 15:33:18

---------------
each day I don't die is cheating
n°515034
chrisbk
-
Posté le 15-09-2003 à 16:30:13  profilanswer
 

(ceux qui ont un compilo optimisant pourrait essayer avec l'exemple de gatorette ?)

n°515038
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 16:38:32  profilanswer
 

je teste comment ? faut mélanger les deux codes source ? (pas envie de chercher là, je veux un truc à copier/coller :D)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515040
chrisbk
-
Posté le 15-09-2003 à 16:41:44  profilanswer
 

toi tu test rien ton borland optimise pas :O
 
(bon si t'as, tu balance le code de gatorette et tu regardes la valeur de la variable statique apres execution, ou tu rajoute un cout<<"kookoo" dans le constructeur)

n°515045
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 16:44:51  profilanswer
 

[Linker Error] Unresolved external '_main' referenced from D:\BORLAND\CBUILDER6\LIB\C0X32.OBJ
 
:o


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515047
chrisbk
-
Posté le 15-09-2003 à 16:46:26  profilanswer
 

Code :
  1. int main()
  2. {
  3. Foo f = f();
  4. }


beta :O

n°515059
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 16:56:48  profilanswer
 

numInstances vaut 2
et ton Foo f = f(); il aime pas, vu que f est pas une fonction mais un Foo :D


Message édité par antp le 15-09-2003 à 16:58:25

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515061
chrisbk
-
Posté le 15-09-2003 à 16:58:26  profilanswer
 

la y'a kooye dans gigot [:ddr555]
 
ah ok c reglé :O


Message édité par chrisbk le 15-09-2003 à 16:58:49
n°515062
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 16:58:38  profilanswer
 

j'ai édité, j'avais mal corrigé ton code :o


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515085
Taz
bisounours-codeur
Posté le 15-09-2003 à 17:19:55  profilanswer
 

ça va ?

n°515097
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 17:30:14  profilanswer
 

oui, et toi ? :)
(:heink:)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515098
Taz
bisounours-codeur
Posté le 15-09-2003 à 17:31:03  profilanswer
 

ché pas, c'est quoi ces manières de upper au bout de 25 jours?  :)


Message édité par Taz le 15-09-2003 à 17:31:33
n°515107
antp
Super Administrateur
Champion des excuses bidons
Posté le 15-09-2003 à 17:42:20  profilanswer
 

c'est pas moi qui ai uppé :o


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°515120
chrisbk
-
Posté le 15-09-2003 à 18:03:16  profilanswer
 

tiens j'avais meme pas fait gaffe qu'il avait 15ans ce topic

n°515133
gatorette
Posté le 15-09-2003 à 18:16:53  profilanswer
 

Je n'avais pas vu non plus qu'il datait tant ce topic.
 

Taz a écrit :

la réponse de Jean Marc Bourget sur fclc++
- en toute circonstance (donc pas uniquement au retour d'une fonction), quand un constructeur de copie devrait être appelé pour copier un temporaire, le compilateur peut utiliser le temporaire à la place (ou plus vraissemblablement contruire directement le temporaire)
- lorsqu'on retourne un objet nommé d'une fonction, on peut utiliser l'objet plutôt que d'en faire une copie (NRVO) (ou plus vraissemblablement mettre l'objet nommé directement à l'endroit ou la valeur de retour de la fonction est attendu, donc même si la norme le permet, je doute qu'un compilateur utilise la NRVO quand dans des chemins différents on retourne des objets nommés différents sauf dans des cas particuliers -- voir ci-dessus)


Je pense que ces affirmations ne prennent pas en compte le cas que j'ai exposé au-dessus. En effet, si le constructeur ou le destructeur ont des effets de bord, il n'est pas possible de faire l'optimisation.


---------------
each day I don't die is cheating
n°515147
Taz
bisounours-codeur
Posté le 15-09-2003 à 18:36:29  profilanswer
 

:heink:
 
 
et dans tous les cas ce détail est laissé libre à l'implémentation. donc il n'y a aucun de problème, sauf pour les conceptions et codes de mauvaises factures


Message édité par Taz le 15-09-2003 à 18:42:46
n°515152
gatorette
Posté le 15-09-2003 à 18:43:34  profilanswer
 

Ben dans mon sujet au-dessus, je présente un cas où un compilateur qui ferait tout le temps l'optimisation ferait une erreur. En effet, en cas d'optimisation, numInstances_ vaudrait 1 alors qu'il doit faire 2.


---------------
each day I don't die is cheating
n°515154
Taz
bisounours-codeur
Posté le 15-09-2003 à 18:46:24  profilanswer
 

mais c'est pas une otpimisation !
la norme dit "on peut faire une copie inutile ou pas"
 
 
et pi je peux te dire le contraire num vaut 2 au lieu de 1


Message édité par Taz le 15-09-2003 à 18:46:53
n°515166
gatorette
Posté le 15-09-2003 à 19:04:11  profilanswer
 

Bon, j'admets m'être misérablement planté...  [:befree]
En relisant en entier l'article que je cite au-dessus, je me suis rendu compte qu'en fait en juillet 1996 le comité ANSI/ISO s'était réuni et autorisait l'élimination de la copie inutile (d'après les conditions énumérées dans DWP
12.8
- c'est quoi ça ?).


---------------
each day I don't die is cheating
n°515171
Taz
bisounours-codeur
Posté le 15-09-2003 à 19:08:28  profilanswer
 

Draft Working Paper

mood
Publicité
Posté le   profilanswer
 


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

  besoin de testeurs: retour de fonction

 

Sujets relatifs
Changer une image en fonction de la sélection d'un menu déroulant ?listbox qui se place en fonction des caracteres tapés
fonction de remplacement de html_entity_decode()Dans excel : affecter un intitulé en fonction d'une valeur
Besoin d'information des système AS 400 (bon connaisseurs demandé)Gestion des erreurs sur la fonction mail.
[php] cherche Fonction pour lire un fichier en phpamnesie: fonction pour obtenir la page qui a appelé le script php ?
[Microsoft SDK] fonction de l'API win pour avoir le Load CPU ?[PHP] passer une fonction dans une action d'un form
Plus de sujets relatifs à : besoin de testeurs: retour de fonction


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