swap idiom

swap idiom - C++ - Programmation

Marsh Posté le 07-11-2009 à 15:11:39    

Quel est l'intérêt de cet idiom, j'ai jamais eu à faire du swap dans mes applis finalement, pourquoi est ce qu'on retrouve ça ici et là ?
pourquoi dans l'operateur dassignement ?
dans l'operateur = on veut pas swaper, on veut affecter....


---------------
.
Reply

Marsh Posté le 07-11-2009 à 15:11:39   

Reply

Marsh Posté le 07-11-2009 à 16:54:31    

quand tu swap pour affecter, tu laisse au systeme la charge de creer la nouvelle mémoire, copier et liberer l'ancienne. C'ets beaucoup plus simple à ecrire, ca evite l'horrible if(this !=asource) et ca a une strong guarantee sur les exceptions.

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

ca a l'air mieux que la vielle forme et ca evite la duplication de code du copy-ctor


Message édité par Joel F le 07-11-2009 à 16:58:07
Reply

Marsh Posté le 07-11-2009 à 18:04:06    

pourtant ici on se retrouve bien à faire de l'auto affectation si ça se produit :  
 
template<class T>
void swap (T &a, T &b)
{
  T temp (a);
  a = b;
  b = temp;
}


---------------
.
Reply

Marsh Posté le 07-11-2009 à 18:09:05    

et d'ailleurs quel est le pbm posé par l'auto-affect ?
 
(2 questions donc au final)


---------------
.
Reply

Marsh Posté le 07-11-2009 à 18:12:05    

C'est bien sûr à ne pas faire si on n'a pas un swap spécialisé pour la classe (soit une spécialisation de std::swap, soit une version dans le namespace de la classe).
 
L'idée derrière le passage par valeur de A -- idiome qu'on ne voit que depuis relativement peu de temps -- est de profiter de la possibilité d'élision du constructeur de copie quand on passe un temporaire.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 07-11-2009 à 18:32:01    

Glock 17Pro a écrit :

pourtant ici on se retrouve bien à faire de l'auto affectation si ça se produit :  
 
template<class T>
void swap (T &a, T &b)
{
  T temp (a);
  a = b;
  b = temp;
}


 
Non ton swap il ets spécialisé pour ta classe et va swapper ses membre :E
l'auto affect c'ets la crap quand tu detruit l'ancien avant d'y copier le nouveau :o

Reply

Marsh Posté le 07-11-2009 à 18:44:38    


C'est bien sûr à ne pas faire si on n'a pas un swap spécialisé pour la classe (soit une spécialisation de std::swap, soit une version dans le namespace de la classe).
 
L'idée derrière le passage par valeur de A -- idiome qu'on ne voit que depuis relativement peu de temps -- est de profiter de la possibilité d'élision du constructeur de copie quand on passe un temporaire.  


 
tout à fait. Rien à rajouter à ça.
 

l'auto affect c'ets la crap quand tu detruit l'ancien avant d'y copier le nouveau :o


 
idem
 


Non ton swap il ets spécialisé pour ta classe et va swapper ses membre :E


 
Pourquoi swapper et ne pas se contenter de faire this->membre1 =  obj.membre1;

Code :
  1. namespace std{
  2. template<>
  3. void swap<MaClasse>(Maclasse& obj)
  4. {
  5. this->IntMembre1 = obj.IntMembre1
  6. // versus  
  7. swap(this->IntMembre1,obj.IntMembre1)
  8. }
  9. }


Message édité par Glock 17Pro le 07-11-2009 à 18:45:33

---------------
.
Reply

Marsh Posté le 07-11-2009 à 18:47:41    

il faut swapper pour que le veil objet soit detruit automagiquement quand la copie sort de scope.

Reply

Marsh Posté le 07-11-2009 à 18:56:26    

merde je vois pas ce que tu veux dire là on a donc
 

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


 
et  

Code :
  1. namespace std{
  2.     template<>
  3.     void swap<MaClasse>(Maclasse& obj)
  4.     {
  5.     swap(this->IntMembre1,obj.IntMembre1)
  6.     }
  7. }


 
à quel endroit ça ne serait pas auto destruct si pas de swap ?


---------------
.
Reply

Marsh Posté le 07-11-2009 à 19:01:43    

Bon, je vais te sortir l'exempel que je file à mes étudiants de première année ...
 
la  bonne vieille classe array<T>  
 

Code :
  1. template<class T> struct array
  2. {
  3.    public:
  4.    array() : data(0), size(0) {}
  5.    ~array()  { if(data) delete[] data; size = 0; }
  6.    array( array<T> const& source )
  7.   {
  8.      data = new T[source.size()];
  9.      size = source.size();
  10.      std::copy(source.begin(),source.end(),this->begin());
  11.   }
  12.   array& operator( array source )
  13.   {
  14.       swap(source);
  15.       return *this;
  16.   }
  17.   // autre methodes trivialles
  18.   protected:
  19.  
  20.   void swap(array& source)
  21.   {
  22.       std::swap(data,source.data);
  23.       std::swap(size,source.size);
  24.   }
  25.    private:
  26.    T* data;
  27.    std::size_t size;
  28. };
  29. template<class T> inline
  30. void swap( array<T>& a, array<T>& b )
  31. {
  32.   a.swap(b);
  33. }


 
L'idée est de swap le contenu du lhs de op= avec le rhs temporaire.
Comme ça, à la sortie de )=, le lhs contient le rhs (affectation) et le rhs contient le lhs. Comme le rhs sort de scope, il est détruit, libérant les ressources de l'ancienne instance

Reply

Marsh Posté le 07-11-2009 à 19:01:43   

Reply

Marsh Posté le 08-11-2009 à 17:11:44    

ah yes j'ai enfin capté, ty.
tu le mets pas dans le std, le swap spécialisé ? c'est inutile ?


Message édité par Glock 17Pro le 08-11-2009 à 17:12:46

---------------
.
Reply

Marsh Posté le 08-11-2009 à 19:12:03    

normalement, t'as pas le droit d'ouvrir std pour y foutre des specialisations.
 
Si tu le mets dans le namespace de ta classe, le Koenig's Lookup va le trouver tout seul.

Reply

Marsh Posté le 08-11-2009 à 19:44:13    

D'après la norme (le dernier draft a une formulation très légèrement différente):

Citation :

It is undefined for a C++ program to add declarations or definitions to namespace std unless otherwise specified.  A program may add template specializations for any standard library template to namespace std.  Such specilization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user-defined name of external linkage and unless the specialization meets the standard library requirements for the original template.


 
Mais attention le swap de Joel n'est pas une specialisation mais une surcharge.
 
Voir http://www.open-std.org/jtc1/sc22/ [...] /n1296.asc


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 09-11-2009 à 13:01:47    

ok , donc un code commme :
 

Code :
  1. namespace std{
  2.         template<>
  3.         void swap<MaClasse>(Maclasse& obj, Maclasse& obj2)
  4.         {
  5.         swap(obj.IntMembre1,obj2.IntMembre1)
  6.         }
  7.     }


 
et tout à fait valide , so


Message édité par Glock 17Pro le 09-11-2009 à 13:02:26

---------------
.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed