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

  FORUM HardWare.fr
  Programmation
  C++

  opérateur =

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

opérateur =

n°1858754
weblook$$
Posté le 07-03-2009 à 14:10:15  profilanswer
 

Une question concernant la bonne manière décrire l'opérateur d'assignement dans une classe
 

Code :
  1. MaClasse& MaClasse::operator =(const MaClasse& Other)
  2. {
  3.    
  4.     MaClasse Temp(Other);
  5.     std::swap(Temp.Ressource, this->Ressource);
  6.     return *this;
  7. }


 
à priorie ce code est un bon exemple de comment faire la chose, mais je me demandais pourquoi utiliser swap au lieu de faire un = ? merci

mood
Publicité
Posté le 07-03-2009 à 14:10:15  profilanswer
 

n°1858780
jesus_chri​st
votre nouveau dieu
Posté le 07-03-2009 à 16:04:37  profilanswer
 

bof, ça dépend des classes.
Le swap c'est pas ce qu'il y a de plus simple ni de plus optimisé, si un simple égal marche, mieux vaut s'en servir. La dépend de la sémentique de la classe.
Noublie pas que le compilateur génère par défaut un opérateur= qui copie membre à membre (et pas bit-à-bit contrairement à ce que tu peux lire sur qlq mauvais sites) et que souvent ça suffit. Enfin, il y a des classes qui ne sont pas copiables/assignables car ça n'a pas de sens. Les classes noncopyable pour reprendre le terme de boost.

n°1858785
Un Program​meur
Posté le 07-03-2009 à 16:28:29  profilanswer
 

weblook$$ a écrit :

Une question concernant la bonne manière décrire
l'opérateur d'assignement dans une classe
 

Code :
  1. MaClasse& MaClasse::operator =(const MaClasse& Other)
  2. {
  3.    
  4.     MaClasse Temp(Other);
  5.     std::swap(Temp.Ressource, this->Ressource);
  6.     return *this;
  7. }


 
à priorie ce code est un bon exemple de comment faire la chose,


 
Le dernier idiome à la mode est

Code :
  1. MaClasse& MaClasse::operator=(MaClasse Other)
  2. {
  3.    swap(*this, Other);
  4.    return *this;
  5. }


En ayant défini une fonction swap dans le même namespace que MaClasse.  Il
y a eu d'autres idiomes à la mode basé sur swap également (celui-ci permet
au compilateur d'enlever la copie dans le cas où on assigne un temporaire).
 

Citation :

mais je me demandais pourquoi utiliser swap au lieu de faire un
=?  merci


 
Les idiomes utilisant swap (sur le même type plutôt qu'à la main comme tu
le fais, en ayant défini une fonction swap ou en ayant spécialisé
std::swap) pour définir operator=, c'est basé sur l'hypothèse que swap ne
jette pas d'exception.  Sous cette hypothèse, c'est une technique
systématique qui s'assure que même s'il faut faire des choses capables de
jeter une exception -- dont allouer de la mémoire --, elles auront lieu
avant le swap et donc on se retrouve avec une "exception safety" forte.
 
Elle n'est pas toujours sans inconvéniants, mais ceux-ci sont relativement
mineurs par rapports aux avantages.  Elle me semble une bonne manière
d'agir tant qu'on n'a pas des bonnes raisons de faire autrement.
 
- il faut écrire une fonction swap -- mais son contenu est aussi
  systématique et pas fondamentalement plus compliqué que ce qu'on écrirait
  dans l'operator=
 
- il faut que le constructeur de copie n'appelle pas l'assignation. Il
  y a des gens qui font

Code :
  1. MaClasse::MaClasse(MaClasse const& Other)
  2. {
  3.    *this = Other;
  4. }


  pour éviter la duplication de code.  Mais cette technique a des
  désavantages en soi qui font que l'éviter n'est pas nécessairement une
  mauvaise idée.
 
- on ne peut pas récupérer ce qui a déjà été alloué pour this et donc on
  peut avoir une consommation supérieure de mémoire.  Si c'est important,
  rien n'oblige à utiliser une technique à base de swap, c'est pas la seule
  manière d'optenir une sémantique de rollback.  Sans elle, il n'y a guère
  qu'une analyse cas par cas.

Message cité 1 fois
Message édité par Un Programmeur le 07-03-2009 à 17:05:36
n°1858791
weblook$$
Posté le 07-03-2009 à 16:57:27  profilanswer
 

Un Programmeur a écrit :

 

Le dernier idiome à la mode est

Code :
  1. MaClasse& MaClasse::operator=(MaClasse Other)
  2. {
  3.    using std::swap;
  4.    swap(*this, Other);
  5.    return *this;
 


 

Merci pour ta réponse détaillée. Un point m'échappe..
La fonction swap utilisée ici est bien celle de la std? tu précises qu'il convient d'en définir une soit même ?
Comment est ce que le code ci-dessus peut appeler cette fonction swap plutot que celle
de la std , puisque tu fais explicitement un using std::swap just au dessus..


Message édité par weblook$$ le 07-03-2009 à 16:59:51
n°1858792
Un Program​meur
Posté le 07-03-2009 à 17:05:09  profilanswer
 

Si tu utilises std::swap et que tu ne l'as pas spécialisé, n'utilises pas cet idiome au risque de te retrouver avec une boucle infinie: std::swap est défini en fonction de l'opérateur =.
 
Pour comment est-ce que la bonne version est trouvée: argument dependant lookup (alias Koenig's Lookup) + résolution de surcharge (qui donne priorité aux fonctions par rappor aux fonctions templates).
 
En fait, dans ce contexte le using n'est pas nécessaire (il l'est quand on écrit des templates et qu'on veut utiliser le swap trouvé par l'ADL s'il y en a un ou celui de std:: s'il n'y en a pas; je corrige mon message).

n°1858800
weblook$$
Posté le 07-03-2009 à 18:23:06  profilanswer
 

ce qui me dérange également ,c'est l'utilité de faire un swap, on s'en fiche que other contienne this ? on veut juste que this contienne other, alors pourquoi swaper?? c'est simplement le nom qui induit en erreur en réalité on ne swappe pas ?

n°1858805
Un Program​meur
Posté le 07-03-2009 à 18:33:20  profilanswer
 

Il est passé par valeur.  Son contenu est détruit à la fin de l'opérateur.

n°1858807
weblook$$
Posté le 07-03-2009 à 18:36:37  profilanswer
 

mais il y a donc des opérations inutiles, il aurait suffit d'affecter plutot que de swapper


Message édité par weblook$$ le 07-03-2009 à 18:37:19
n°1858809
Un Program​meur
Posté le 07-03-2009 à 18:43:05  profilanswer
 

Mesures et quand tu trouves un cas où la différence est significative, tu passes à d'autres techniques.

 

Le gros avantage de cet idiome, c'est qu'il te donne par construction un comportement correct, même quand il peut y avoir des exceptions.  D'autres méthodes te donne le même résultat, mais ne sont pas systématiquement applicable.  Et parfois tu n'as pas besoin du rollback en cas d'exception.  Mais il me semble que c'est une bonne technique à utiliser tant qu'on n'a pas de bonnes raisons pour faire autrement.


Message édité par Un Programmeur le 07-03-2009 à 18:46:03
n°1858819
weblook$$
Posté le 07-03-2009 à 19:00:36  profilanswer
 

ok thx

mood
Publicité
Posté le 07-03-2009 à 19:00:36  profilanswer
 

n°1858858
Joel F
Real men use unique_ptr
Posté le 07-03-2009 à 22:30:34  profilanswer
 

l'operatro= definit par swap est relativement sexy et le sera d'autant plus lorsqu'on aura un vrai semantique de move avec les rvalue references

n°1859111
weblook$$
Posté le 08-03-2009 à 23:13:46  profilanswer
 

Finalement je me rends compte que je n'arrive pas avoir le cas ou la non spécialisation de l'opérateur = peut poser problème...
Dans quel  cas y a t-il le même problème qu'on retrouve avec le constructeur de recopie (lorsque qu'un membre par exemple est un pointeur) ?

 

L'opérateur = n'est appelé que lorsqu'une fonction retourne un Objet de la classe

 

A& func(A& a)
{
return a;
}

 

f=func(f1); //appelé ici

 

Mais étant donné qu'il s'agit d'une référence qui est retourné, il n'y pas le problème d'un pointeur non valide

 

c'est utile uniquement dans le cas où l'on écrit :

 

A a;
A a1;
a=a1;

 

?

 

bref j'aurais besoin d'un petit éclairssissement svp

 


Message édité par weblook$$ le 08-03-2009 à 23:27:18
n°1859153
Un Program​meur
Posté le 09-03-2009 à 09:35:54  profilanswer
 

Qui va detruire l'objet pointe si tu copies un pointeur?

n°1859237
weblook$$
Posté le 09-03-2009 à 11:45:53  profilanswer
 

oups oui, en me levant ce matin tout était plus clair... :$, effectivement dans le cas du retour de fonction, on aura bien in fine deux objets ayant chacun un membre pointant vers la même adresse mémoire donc problème lors de la destruction car double delete sur une même adresse, et si de plus on alloue ce membre dans le constructeur, on aura aussi une fuite de mémoire, car l'adresse mémoire initiale du membre donné de type pointeur appartenant à l'objet recevant le retour de fonction ne sera jamais désaoullé, enfin si j'ai bien tout compris !
 
 
Mais j'ai encore un point que je ne comprends pas, dans l'exemple ci-dessous je passe l'argument par référence et non par valeur, et tout semble Ok
 

Code :
  1. struct Bar
  2. {
  3. int * p;
  4. Bar():p(new int(2)){}
  5. Bar& operator =(const Bar& f) //REF
  6. {  
  7.   std::swap(*p,*f.p);
  8.   return *this;   
  9. }
  10. ~Bar()
  11. {
  12.  delete p;
  13. }
  14. };
  15. int main()
  16. {
  17. Bar a, b;
  18. *a.p=3;
  19. b=a;
  20. system("pause" );
  21. }


Message édité par weblook$$ le 09-03-2009 à 12:07:06
n°1859240
weblook$$
Posté le 09-03-2009 à 11:50:09  profilanswer
 

Bon j'enchaine lol, j'ai également rencontré un problème en utilisant le fameux std::swap, dans le code suivant :

 
Code :
  1. #include <iostream>
  2. #include <algorithm>
  3. struct Bar
  4. {
  5. int nb;
  6. Bar():nb(4){}
  7. Bar& operator =(const Bar f)
  8. {  
  9.   std::swap(nb,f.nb); //NOK
  10.   return *this;   
  11. }
  12. };
  13. int main()
  14. {
  15. int nb,n;
  16. std::swap(nb,n); //OK
  17. system("pause" );
  18. }
 


Le swap dans l'operator = ne passe pas, le compilateur me dit (Visual 08), void std::swap(_Ty &,_Ty & )' : paramètre modèle '_Ty' ambigu

 

:??:


Message édité par weblook$$ le 09-03-2009 à 11:51:21
n°1859510
weblook$$
Posté le 09-03-2009 à 20:14:51  profilanswer
 

ok c'est le const qui foutait le bordel... mais un const_cast<int>(f.nb) ne marche pas , ça me suprend.. obliger de fire un static_cast, à moins de faire

 
Code :
  1. std::swap<int>(nb,*const_cast<int*>(&f.nb));


Message édité par weblook$$ le 09-03-2009 à 20:17:56

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

  opérateur =

 

Sujets relatifs
problème surcharge opérateurfaire des macros avec l'operateur << windows et linux
operateur d'affectation[C#.NET] Surcharger l'operateur " ++ " pour une hashtable, comment ?
[c++] operateur affectation[Résolu ]Opérateur de comparaison en python
surcharge de l'opérateur [][][C++] Surchage de l'opérateur []
[C++] Problème avec l'opérateur %[Mysql] opérateur 'ou'
Plus de sujets relatifs à : opérateur =


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