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

SL & STL C++ Discussion :

vector<vector<T> > et push_back()


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Par défaut vector<vector<T> > et push_back()
    Salut à tous,

    j'ai un soucis à base de vector et de push. Je vais essayer de vous résumer ça :

    J'ai 2 classes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class MaPetiteClasse
    {
    public :
    MaPetiteClasse()
    MaPetiteClasse(params...)
    ~MapetiteClasse()
    operator=(...)
    MaPetiteClasse(const MaPetiteClasse &m)
     
    private : 
    //des données statiques uniquement
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template <class T>
    class MaGrosseClasse
    {
    private : 
    vector<T> toto;
    //d'autres données, toutes statiques
     
    public:
    //idem au dessus, un constructeur par défaut, un constructeur avec des params, un =, un constructeur de recopie et un destructeur.
     
    };

    J'instancie un MaGrosseClasse<MaPetiteClasse>. J'ai un vector<MaGrosseClasse> et il m'arrive de faire des push_back() dedans. Le problème est que le contenu statique de MaGrosseClasse est correctement recopié dans le vector<MaGrosseClasse>, mais pas le vector<MaPetiteClasse>.

    Pour info :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    template <class T>
    MaGrosseClasse<T>::MaGrosseClasse(const class MaGrosseClasse<T> & c)
    {
    //bete copie des data statiques
    (...)
     
    for(int i = 0 ; i < c.size() ; i++)  //MaGrosseClasse::size() renvoie toto.size();
    	{
    		T t = c.GetItem(i);
    		items.push_back(t);
     
    	}
    }

    Ce qui me surprend le plus c'est que, en suivant pas à pas le déroulement de ce constructeur de recopie, tout se passe comme il faut, le vector est bien recopié, mais dès qu'on sort de la fonction, toto redevient vide.
    Si vous avez des idée, je suis preneur.

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Fais directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <class T>
    MaGrosseClasse<T>::MaGrosseClasse(const class MaGrosseClasse<T> & c)
      : toto( c.toto )
    {
    ...
    }
    ps: j'imagine que toto et items c'est les mêmes ?

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    J'ai un peu de mal à comprendre mais quelques éléments :
    -> Les membres statiques d'une classe n'ont pas besoin d'être recopiés dans le constructeur de copie ou dans l'opérateur d'affectation. Les membres statiques d'une classe sont partagés par toutes les instances de la classe.
    -> Si tu ne créés pas de constructeur de copie ou d'opérateur d'affectation sur une classe, le compilateur en créé automatiquement un qui se contente d'appeler le constructeur de copie des membres/classes parentes. Prise à l'envers cette phrase se formule : si tu ne fais rien d'autre dans ton constructeur de copie/opérateur d'affectation que de copier tes membres de l'un vers l'autre ... et bien ne définis pas ces deux méthodes et laisse le compilateur les générer automatiquement (et souvent sans erreur).
    Pour plus d'information, je t'invite à consulter la F.A.Q. :
    Quand dois-je définir un constructeur par copie ?
    Quand dois-je définir l'opérateur d'affectation ?
    Qu'est-ce que la forme canonique orthodoxe de Coplien ?
    Que conclure de la forme canonique orthodoxe de Coplien ?
    Pourquoi déclarer un membre static dans une classe ?

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Par défaut
    bonjour,

    j'ai pas compris grand chose non plus, mais comme indiqué il
    ne sert à rien de copier les statiques car ils sont communs à
    toutes les instances de la classe, pour le vecteur il suffit
    d'utiliser son opérateur d'affectation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    vector< T > toto1, toto2;
    ....
    toto2 = toto1;
    // c'est tout, pas besoin d'itérer, chaque élément doit
    // avoir un constructeur par recopie bien entendu.
    Pour résumer, constructeur par recopie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    MaGrosseClasse<T>::MaGrosseClasse(const class MaGrosseClasse<T> & c)
    {
        *this = c; // affectation.
    }
    Puis opérateur d'affectation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <class T>
    MaGrosseClasse<T> &MaGrosseClasse<T>::operator=(const class MaGrosseClasse<T> & c)
    {
       if( &c != this ) // histoire de ne pas se recopier sur soi même.
       {
          toto = c.toto; // copie du vecteur.
       }
       return *this; // pour l'égalité multiple ( a =b = c = ...)
    }
    Bon courage!

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Citation Envoyé par ads59 Voir le message
    Pour résumer, constructeur par recopie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    MaGrosseClasse<T>::MaGrosseClasse(const class MaGrosseClasse<T> & c)
    {
        *this = c; // affectation.
    }
    Puis opérateur d'affectation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <class T>
    MaGrosseClasse<T> &MaGrosseClasse<T>::operator=(const class MaGrosseClasse<T> & c)
    {
       if( &c != this ) // histoire de ne pas se recopier sur soi même.
       {
          toto = c.toto; // copie du vecteur.
       }
       return *this; // pour l'égalité multiple ( a =b = c = ...)
    }
    Bon courage!
    Comme dit dans les référence à la F.A.Q., si le contructeur par copie et l'affectation consiste à faire ça, alors ne pas les définir. Le compilateur s'en charge sans problème et en appelant correctement.
    Si d'aventure tu souhaites vraiment les redéfinir, le constructeur par copie (comme tous les constructeurs) devrait privilégier les listes d'initialisations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <class T>
    MaGrosseClasse<T>::MaGrosseClasse(const class MaGrosseClasse<T> & rhs_)
    :toto(rhs_.toto)
    {}
    Et l'opérateur de copie devrait utiliser l'idiome copy&swap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    emplate <class T>
    MaGrosseClasse<T> &MaGrosseClasse<T>::operator=(MaGrosseClasse<T> rhs_)
    {
       swap(toto,rhs_.toto);
       return *this;
    }

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Par défaut
    Tout à fait d'accord, le compilo s'en sort bien, et la forme avec liste
    d'init est bien aussi...sauf, selon moi, en cas de multi-threading, d'où
    l'habitude que j'ai d'écrire la forme de coplien pour locker ce qui doit l'être...

    ok pour ce qui est l'idiome "copy-and-swap", mais il rajoute
    de la copie temporaire (rhs_ est passé par valeur et sert de variable locale
    RAII), ce qui peut être coûteux en perfs sur de gros objets.

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/05/2007, 00h20
  2. Réponses: 8
    Dernier message: 22/12/2006, 22h36
  3. vector de vector
    Par Clark dans le forum SL & STL
    Réponses: 15
    Dernier message: 07/04/2006, 20h11
  4. [ Vector Fichier ] Vector dans fichier texte
    Par geegee dans le forum Langage
    Réponses: 5
    Dernier message: 21/05/2004, 13h56
  5. [Vector] classe Vector et exception
    Par Nanoua dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 23/04/2004, 12h37

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