CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C++] constructeur par recopie

godrik
godrik
Niveau 30
30 juillet 2008 à 12:49:23

Bonjour,
je viens vers vous a cause d'un comportement inatendu d'un programme tres simple disponible a l'adresse suivante:
http://godrik.mandragor.org/~godrik/dummy.cpp

il semblerait que le constructeur par recopie ne soit pas appelé. En effet la sortie standard affiche:

default
afficher 1
dstr

Je pensais que l'objet p1 serait construit par recopie de l'objet retourné par "fonction".

Quel est mon erreur dans ce raisonnement ? S'agit il d'une optimisation du compilateur ?
merci

dnob700
dnob700
Niveau 10
30 juillet 2008 à 13:32:37

Ça ressemble à une optimisation de gcc qui ne construit pas d'objet intermédiaire. Le constructeur "default" est appelé dans fonction et c'est son résultat qui est stocké dans p1. En fait fonction agit comme un constructeur.

Ça ressemble à cette extension de gcc : http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_5.html#SEC106
même si tu ne l'utilise pas explicitement.

On pourrait penser qu'il faudrait appeler une fois le constructeur default et une fois le constructeur par copie, mais si j'ai bonne mémoire, il y a aussi une limitation de gcc qui l'empêche de transformer une instance en une référence quand il s'agit du retour d'une fonction (mais ça a pu évoluer). Donc il sera obliger d'allouer une variable temporaire, ce qui ne serait pas très efficace. Ça fait une double raison pour optimiser cet appel.

AmishParadise
AmishParadise
Niveau 5
30 juillet 2008 à 13:36:48

En fait le compilateur considère "dummy p1(fonction('t'));" comme une affectation de référence, vu que tu n'auras plus aucun autre moyen d'accéder à l'objet retourné par fonction('t').
plutôt que de copier puis détruire fonction('t'), il remplace juste p1 par fonction('t').
si tu ajoutes un autre moyen potentiel d'accéder au "p de fonction" en le mettant en static, ou en le transformant en pointeur, "dummy p1(fonction('t'));" deviens alors une copie.

AmishParadise
AmishParadise
Niveau 5
30 juillet 2008 à 13:37:17

erf trop lent :-p

godrik
godrik
Niveau 30
30 juillet 2008 à 13:39:45

Je pense aussi a une optimisation du compilateur, je me demande si ce comportement peux poser des problèmes. En tout cas, il ne semble pas être conforme a la norme (bien que l'optimisation soit probablement valide dans 99% des cas d'utilisations).

J'ai tenté de faire un autre effet de bord dans le constructeur par recopie (incrémenté une variable globale). La variable n'est jamais incrémenté.

Si j'incremente tmp dans le cstr par recopie, il n'est pas incrémenté non plus.

godrik
godrik
Niveau 30
30 juillet 2008 à 14:46:40

Je viens de tester avec 3 version de gcc et pgcpp, les trois ont le meme comportement.
C'est peut etre dans la norme finalement...

dnob700
dnob700
Niveau 10
30 juillet 2008 à 15:49:20

je viens de tester avec icc et ça fait pareil aussi.

godrik
godrik
Niveau 30
30 juillet 2008 à 20:18:29

bon, finalement c'est peut etre dans la norme comme cela. Quelqu'un a un access au ARM pour confirmer ?

kufa
kufa
Niveau 9
31 juillet 2008 à 02:19:45

oui c est dans la norme (12.8.15):

"Whenever a temporary class object is copied using a copy constructor, and this object and the copy have the
same cv-unqualified type, an implementation is permitted to treat the original and the copy as two different
ways of referring to the same object and not perform a copy at all, even if the class copy constructor or
destructor have side effects. For a function with a class return type, if the expression in the return statement
is the name of a local object, and the cv-unqualified type of the local object is the same as the function
return type, an implementation is permitted to omit creating the temporary object to hold the function return
value, even if the class copy constructor or destructor has side effects. In these cases, the object is
destroyed at the later of times when the original and the copy would have been destroyed without the opti-
mization."

godrik
godrik
Niveau 30
31 juillet 2008 à 09:45:46

merci kufa de cette précision. Ce n'est donc pas un bug

dnob700
dnob700
Niveau 10
31 juillet 2008 à 12:43:53

mais c'est pas mal. Je pense qu'un bon langage OO devrait interdire d'écrire des opérateurs qui ne se conduisent pas comme on s'y attend (un constructeur avec effet de bord, un operator+ pas associatif, etc.). Une optimisation de ce genre force un petit peu à se conformer à cette règle.

godrik
godrik
Niveau 30
01 août 2008 à 18:22:16

je pense en effet que le C++ autorise des choses vraiment vraiment trop sales.
Par exemple, le langage devrait forcer que deux objets copiés (ou affectés) soient égaux (au sens de l'opérateur ==).
Bref la construction/destruction/affectation/comparaison d'objet est vraiment faite pour qu'on se tire une balle dans le pied.
Il y a des jours ou je trouve ca tres bien. D'autres, je me dis que stroustrup aurait mieux fait de s'abstenir...

kufa
kufa
Niveau 9
01 août 2008 à 20:05:55

comme bon extremiste du c++, j aime bien les portes ouvertes qui existent dans la norme; mais ca rend la programmation bien plus difficile, et peu de personne maitrisent ces aspects pas tres courants voir obscures, et souvent bien complexes..
Cela dit il faut tjs faire gaffe aux constructeurs ou autres operateurs=, et bien maitriser son sujet (nonon pas d exceptions dans un constructeur/destructeur please).

le langage devrait forcer que deux objets copiés (ou affectés) soient égaux (au sens de l'opérateur ==)

Je vois pas pkoi tu voudrais ca? Par exemple si tu veux avoir un unique id par instance et que ton operateur== renvoie true si et seulement si les ids sont egaux (sans checker le content qui se teste par exemple via une autre routine). Pas beau, mais je vois pas pkoi la norme devrait interdire ca.

Bref la construction/destruction/affectation/comparaison d'objet est vraiment faite pour qu'on se tire une balle dans le pied

Comme tout le reste du language ;)

Sous forums
  • Aide à l'achat Mac
  • Macintosh
  • Création de Jeux
  • Programmation
  • Création de sites web
  • Linux
  • Internet
  • Steam Deck
  • Hardware
La vidéo du moment