IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Constructeur de copie, et opérateur d'affectation.


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut Constructeur de copie, et opérateur d'affectation.
    Bonjour à tous,

    Pour les classes à sémantique de valeur, on définie très souvent, un constructeur de copie ou un opérateur d'affectation= . J'aimerais savoir quelles sont les différences entre ces deux méthodes particulière. Est-ce qu'elles jouent eux deux le même rôle ? Et dans quel cas et but les utilise-t-on ?

    Merci à ceux qui apporteront des réponses à mes questions.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MaClasse(const &MaClasse);
    MaClasse& operator=(const &MaClasse);

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    Bonsoir,

    copie et affectation ne sont pas la même chose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class C { ... };
    C c1; // constructeur
    C c2(c1); // constructeur par copie
     
    c2 = c1; // affectation

  3. #3
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Comme son nom l'indique, le constructeur par copie construit un nouvel objet, alors que l'opérateur d'affectation opère sur un objet existant.

    Par exemple, un quiz classique : Qu'affiche chacune des lignes suivantes ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include <iostream>
    struct MaClasse
    {
       MaClasse(){std::cout << "Default Ctor\n"; }
       MaClasse(const MaClasse&){std::cout << "Copy Ctor\n"; }
       MaClasse& operator=(const MaClasse&){std::cout << "Op = \n"; return *this;}
    };
     
    int main()
    {
       MaClasse m1;
     
       MaClasse m2(m1);
       MaClasse m3 = m2;
       MaClasse m4 = MaClasse();
     
       m1 = m2;
    }

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    vu ma réponse précédente cela ne devrait pas être trop difficile
    (je suppose qu'on a commencer à répondre en même temps et que j'ai fini avant, mais comme on ne peut pas prendre de mutex pour rendre les réponses exclusives ... )

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Bien qu'ils soient appelé à des moments différents, ils font la même chose (il n'y qu'a voir l'idiom copy & swap). Donc si tu dois en définir un, tu dois aussi en définir l'autre.

  6. #6
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Pensez à privilégier l'affectation par copy and swap pour les objets contenants des ressources à copier. ca a aussi l'avantage d'eviter la duplication de code entre C(C const&) et operator=(C const&)

  7. #7
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    J'vais quand même corriger mon p'tit code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    C & operator=(C v)
    {
     swap(v.members,this->members);
     return *this;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    C & operator=(C const & v)
    {
     C tmp(v);
     swap(tmp.members,this->members);
     return *this;
    }
    J'espère que c'est plus mieux comme ça (il fait tard à c't'heure, il fait fatigué...)

    Mais c'est quand même la première fois que je vois le copy&swap remit en cause. Il est pourtant prouvé que c'est la cata de ne pas l'utiliser en cas de références cycliques.

    EDIT: et m.... j'ai édité au lieu d'ajouter un post... allez dodo...

  8. #8
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    bigre diantre, quand j'écris a=b je ne veux surtout pas modifier b !

    ce qui est curieux c'est donc d'utiliser swap, qu'elle idée aussi sotte que grenue

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Bah, tu crées la copie (RAII etc) au passage. Mais là où tu gagnes c'est dans par exemple ce genre de cas :

    C makeC();
    C c;
    c = makeC();

    Ici comme le paramètre bind à une rvalue, la copie est (tout le temps?) passée à la trappe.

    @Bruno_pages : sisi ... le copy and swap est LA bonne façon de faire. Et rien n'est modifié hein. (pour ça qu'on crée une copie temporaire).

  10. #10
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    bigre diantre, quand j'écris a=b je ne veux surtout pas modifier b !

    ce qui est curieux c'est donc d'utiliser swap, qu'elle idée aussi sotte que grenue
    Je pense que t'as pas bien compris.
    Je viens de retrouver l'article qui en parle ici

  11. #11
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je pense que t'as pas bien compris.
    mais si, mais toi tu supposes que le copy constructeur fait bien son travail, ci c'est pas le cas

    de plus faire un échange c'est intrinsèquement faire 3 affectations, et dans ton deuxième cas il y en a même 4 avec la copie, et tout cela pour en faire en fait une seule

  12. #12
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Si c'est toi qui implémente l'op= alors c'est que c'est aussi toi qui implémente le constructeur de copie... (ou alors y'a un truc qui cloche, mais dans tout les cas tu y'a accés).

    Et de toute façon si le constructeur de copie fait pas son boulot comme tu le sous entends, alors y'a des soucis plus grave que ça . (ie ça pétera avant).

    Quand à la rapidité c'est une blague?
    Sachant que quand on l'implémente c'est qu'il est non trivial (ie manipulation de donnée sur le tas etc) on l'écrirait comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    C& operator=(const C& other)
    {
           delete foo; // on suppose qu'on a T* foo
           foo = new T(*other.foo);
     
           return *this;
    }
    Ce qui est bien plus couteux qu'un swap. (et je parle même pas du non-idiome qu'est le test anti-auto affectation).

    Bref oui le copy-and-swap est LA BONNE façon de faire un opérateur =, et ça fait longtemps que ça a été prouvé. (et si tu tiens à t'en convaincre tu peux regarder comment font les implémentations de la STL et boost).

  13. #13
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    incroyable !

    d'abord tu dois écrire C & operator=(C v) ce qui provoque une première recopie car passage par valeur, ensuite swap fait un échange forcément plus cher qu'une affectation (même si tu ne vois pas cette partie du code elle s'exécute bien), ton delete tu le trouveras de toute façon même s'il n'est pas sur le même objet, et enfin une classe ne contient pas que des pointeurs ce que tu sembles supposer

    Quand à la rapidité c'est une blague?
    oh non la rapidité n'est pas une blague, par contre la majorité des softs développés sont effectivement des usines à gaz qui occupent mémoire et CPU de façon éhontés

  14. #14
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    d'abord tu dois écrire C & operator=(C v) ce qui provoque une première recopie car passage par valeur
    Oui c'est un peu le but, créer un temporaire pour pouvoir le swapper... (et aussi dans certains cas profité de la copy-elision... comme je l'ai dis :s)

    Citation Envoyé par bruno_pages Voir le message
    et enfin une classe ne contient pas que des pointeurs ce que tu sembles supposer
    ??? T'es entrain de dire que tu surcharges l'op= même quand il est trivial? Je suppose pas qu'une classe contient que des pointeurs hein... c'est juste qu'en général quand j'ai a écrire un op= c'est que la classe contient des pointeurs et que le compilateur est pas capable de s'en sortir par lui même... Le reste du temps je le laisse se débrouiller.

  15. #15
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    incroyable !

    d'abord tu dois écrire C & operator=(C v) ce qui provoque une première recopie car passage par valeur, ensuite swap fait un échange forcément plus cher qu'une affectation (même si tu ne vois pas cette partie du code elle s'exécute bien), ton delete tu le trouveras de toute façon même s'il n'est pas sur le même objet, et enfin une classe ne contient pas que des pointeurs ce que tu sembles supposer


    oh non la rapidité n'est pas une blague, par contre la majorité des softs développés sont effectivement des usines à gaz qui occupent mémoire et CPU de façon éhontés
    T'as pas lu ceci, le revoici: Want speed ? Pass by value.
    Et puis le swap se fait sur chacun des membres de la classe bien sûr. Et on utilisera les formes spécialisées quand elles sont prévues (comme dans vector, string, etc).

    Enfin, comme je le disais, c'est la première fois que je vois le copy&swap remis en question.

  16. #16
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968

  17. #17
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 632
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 632
    Points : 30 711
    Points
    30 711
    Par défaut
    Salut,
    Citation Envoyé par Davidbrcz Voir le message
    Bien qu'ils soient appelé à des moments différents, ils font la même chose (il n'y qu'a voir l'idiom copy & swap).
    Justement, non... Il ne font pas la même chose...

    Le premier se contente de copier l'objet, le second assigne la copie des valeurs d'un objet donné à un autre
    Donc si tu dois en définir un, tu dois aussi en définir l'autre.
    Par contre, là dessus, on est d'accord (il y a d'ailleurs de fortes chances pour que tu doive également fournir une implémentation du destructeur, parce que les trois sous entendent que la simple copie "membre à membre" sera insuffisante, entre autres du fait de la présence de pointeur

    Citation Envoyé par bruno_pages Voir le message
    bigre diantre, quand j'écris a=b je ne veux surtout pas modifier b !
    Justement, en passant un argument sous forme de valeur et non sous forme de référence à ton opérateur d'affectation, tu effectue d'office une copie de l'objet, cette copie étant... temporaire (n'existant que pour la durée de la fonction, qui est ici l'opérateur d'affectation).
    ce qui est curieux c'est donc d'utiliser swap, qu'elle idée aussi sotte que grenue
    Là encore, c'est des plus normal: si tu décide d'implémenter tes propres constructeurs par copie et opérateurs d'affectation, c'est parce que, encore une fois, la copie membre à membre ne donnera pas les résultats escomptés (parce qu'il y a au minimum un pointeur qui, s'il venait à être copié, ferait qu'une même adresse mémoire serait partagée par deux objets pourtant clairement différents).

    Comme la variable temporaire créée à l'occasion de la copie est générée sans avoir recours à l'allocation dynamique, elle sera d'office détruite une fois que l'on sortira de la portée de la fonction, ce qui implique que son destructeur sera appelé automatiquement.

    On compte donc sur le fait que le destructeur sera appelé (et correctement implémenté) pour estimer qu'il suffira d'échanger les pointeurs (cela revient simplement à intervertir les adresses mémoires vers lesquelles ils pointent ) pour que la propriété de la mémoire allouée à l'objet en cours d'une part et celle du pointeur respectif de la copie soit intervertie (l'objet en cours devenant propriétaire de la mémoire allouée à la copie et inversement).

    Lorsque la copie sera détruite et son destructeur appelé( cela arrivera automatiquement ), nous aurons la certitude que la mémoire qui était, à l'origine, allouée à l'objet en cours sera correctement libérée, et nous éviterons donc tout risque de fuite mémoire.

    Maintenant, il est aussi vrai que le swap ne se justifie par exemple pas pour de simples variables de type primitif: une simple affectation étant amplement suffisante pour ces dernières
    Citation Envoyé par Goten Voir le message
    Oui c'est un peu le but, créer un temporaire pour pouvoir le swapper... (et aussi dans certains cas profité de la copy-elision... comme je l'ai dis :s)
    Hé oui, le but est bel et bien de profiter d'un temporaire pour assurer... la libération correcte de la mémoire allouée dynamiquement (pour ce qui est des membres non pointeurs, l'intérêt devient nul )
    ??? T'es entrain de dire que tu surcharges l'op= même quand il est trivial? Je suppose pas qu'une classe contient que des pointeurs hein... c'est juste qu'en général quand j'ai a écrire un op= c'est que la classe contient des pointeurs et que le compilateur est pas capable de s'en sortir par lui même... Le reste du temps je le laisse se débrouiller.
    Et c'est d'ailleurs ce qu'il faut faire...

    Par défaut, le compilateur fournit quatre fonctions particulières:
    1. un constructeur trivial (ne prenant pas d'argument) dont le comportement est d'appeler le constructeur trivial de chaque membre non statique de la classe dans l'ordre de leur déclaration
    2. un constructeur par copie, dont le comportement est d'appeler le constructeur par copie de chaque membre non statique de la classe en leur passant les membre respectifs de l'objet passé en paramètre
    3. Un opérateur d'affectation appelant l'opérateur de chaque membre non statique de la classe avec les membres respectifs de l'objet passé en paramètre
    4. Un destructeur dont le comportement est d'appeler le destructeur de chaque membre non statique de la classe, dans l'ordre inverse de leur déclaration
    Ces quatre fonctions particulières sont réputées publiques, inlines, non statiques et non virtuelles (enfin, ce dernier point ne s'applique de toutes manières qu'au destructeur )

    Le constructeur trivial ne sera généré que s'il n'y a aucun autre constructeur déclaré par le programmeur, les autres fonctions ne seront générées que si le programmeur ne les déclare pas lui-même.

    Il n'y a donc aucune raison de définir ces quatre fonctions si le comportement que l'on peut en attendre correspond au comportement implémenté par défaut par le compilateur

    Par contre, dés le moment où l'on définit l'une des trois dernières fonctions (constructeur par copie, opérateur d'affectation ou destructeur), il faudra envisager de respecter la forme canonique de Coplien et définirad minima les deux autres (et soit un constructeur trivial, soit un constructeur prenant un (des) argument(s) ), du moins pour les classe ayant sémantique de valeur (pour les classes ayant sémantique d'entité, nous aurons généralement tendance à les déclarer privé et à ne pas les définir, de manière à interdire la copie et l'affectation... en attendant C++11 et le nouveau sens que la norme donne au mot clé delete )

    Or, le seul cas où le comportement par défaut ne nous intéresse pas (du moins, lorsque l'on a affaire à une classe ayant sémantique de valeur), c'est le cas où une classe manipule un pointeur dont elle garde la responsabilité de la gestion de la mémoire.

    Dans ce cas, l'idiome copy and swap reste, effectivement, la seule bonne solution possible pour éviter les problèmes de fuite mémoire et de tentative de double libération de la mémoire

  18. #18
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    et j'ai bien spécifié que ce ne s'appliquait que au cas ou la copie impliquait des ressources lourdes

    apres, si tu sais pas ecrire proprement le swap d'un truc genre vector, la forcement ...

  19. #19
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 534
    Points : 6 723
    Points
    6 723
    Par défaut
    Citation Envoyé par Goten Voir le message
    ??? T'es entrain de dire que tu surcharges l'op= même quand il est trivial?
    un petit rappel en passant, l'inverse de la proposition "ne contient pas que des pointeurs" n 'est pas "contient aucun pointeur"

    Citation Envoyé par camboui Voir le message
    Et puis le swap se fait sur chacun des membres de la classe bien sûr..
    c'est bien là le problème, car il s'appliquera aussi aux membres ou l'affectation est triviale comme les nombres, d'où la lourdeur et l'inefficacité de la chose

  20. #20
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 632
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 632
    Points : 30 711
    Points
    30 711
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    c'est bien là le problème, car il s'appliquera aussi aux membres ou l'affectation est triviale comme les nombres, d'où la lourdeur et l'inefficacité de la chose
    Sur ce point, je suis effectivement d'accord qu'il ne faut pas swaper tout et n'importe quoi...

    Le swap d'un int ou d'un double ne me semble par exemple clairement pas une bonne idée, et je serais presque d'avis de dire qu'il ne faut swaper que les membres... pour lesquels l'opérateur d'affectation n'est pas défini et les pointeurs (car il est défini, mais de manière incorrecte par rapport à l'usage qui sera fait du pointeur).

    Le problème auquel on peut alors être confronté, c'est que l'on doit avoir une confiance absolue dans le fait que l'opérateur d'affectation des type ayant sémantique de valeur que l'on utilise comme membre sera, effectivement, correctement implémenté, mais c'est peut être mon coté parano qui ressort là dessus

Discussions similaires

  1. Réponses: 1
    Dernier message: 03/02/2015, 16h21
  2. Réponses: 7
    Dernier message: 17/08/2014, 16h20
  3. Réponses: 96
    Dernier message: 08/04/2013, 12h54
  4. Constructeur de copie et Template: Transtypage
    Par ikkyu_os dans le forum Langage
    Réponses: 9
    Dernier message: 26/12/2004, 23h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo