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

Langage C++ Discussion :

vector et copy constructor


Sujet :

Langage C++

  1. #1
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut vector et copy constructor
    Bonjour, prenons le code suivant:
    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
    20
    21
    #include <iostream>
    #include <vector>
    #include <string>
     
    using namespace std;
     
    struct Foo
    {
    	Foo( const string & name = "unknown" ) : name( name ) { cout << "ctor" << endl; }
    	Foo( const Foo & other ) : name( other.name ) { cout << "copy ctor" << endl; }
    	Foo & operator = ( const Foo & other ) { name = other.name; cout << "operator =" << endl; }
     
    	string name;
    };
     
    main()
    {
    	vector< Foo > v;
    	v.push_back( Foo() );
    	getchar();
    }
    L'ouput donne:
    ctor
    copy ctor
    Ce qui signifie que le constructeur de copie de Foo est appelé lors du push_back.

    Pourquoi fait-il cette copie? Comment l'éviter (étant entendu que l'on ne connait pas à l'avance le nombre d'éléments que l'on va mettre dans le vecteur)?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  2. #2
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    std::vector gère la vie de ses objets et en fait donc une copie.
    De plus, std::vector gère un tableau dynamique. Lorsque la taille du tableau est trop petite, il en alloue un nouveau et recopie tous les éléments.

    Il faut utiliser un std::vector de pointeurs intelligents.

  3. #3
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Ici:

    Tu as

    qui construit l'objet, qui est un objet temporaire.

    Puis l'objet temporaire est passe a push_back qui copie cet objet dans l'array que le vector gere.

    Par contre, il me semble que certains compilos vont eliminer la copie si tu compile en optimise (pas en Debug). Cela dis ce n'estpas garanti.

    En C++03, ce n'est pas possible de garantir qu'il ny aura pas cette copie.

    En revanche, C++11 offre une solution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v.emplace_back( /* arguments du constructeur de Foo ici */ );
    En gros ca construit l'objet directement dans l'array geree par le vector, en lui passant les arguments de construction que tu lui files (ici, constructeur par defaut, pas d'arguments).

    Ca resouds le probleme. Mais il faut un compilateur et une bibliotheque standard C++11.

  4. #4
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Klaim Voir le message
    En revanche, C++11 offre une solution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v.emplace_back( /* arguments du constructeur de Foo ici */ );
    ça semble en effet résoudre le problème, merci

    Je viens de tester sur vs 2010, mais visiblement il y a une limitation: emplace_back prend un et un seul argument (donc pas possible d'utiliser directement avec des constructeurs prenant zero ou plusieurs arguments). Limitation facile à contourner, mais limitation tout de même. D'ailleurs, peut-être que couplé avec une inplace_factory de boost, ça pourrait donner des trucs assez magiques
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Points : 158
    Points
    158
    Par défaut
    emplace_back prend un et un seul argument
    Heu, non, le prototype de emplace_back est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template< class... Args >
    void emplace_back( Args&&... args );

  6. #6
    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
    Dans le standard emplace_back peut prendre un nombre arbitraire d'argument mais, sur vs2010, vu l’absence de template variadique microsoft a implémenté une version restreinte d'emplace_back qui ne prend qu'un seul argument. (c'est un peu mieux sur vs2012 où l'on peut aller jusqu'à 4 arguments)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. vector et copie
    Par vince3320 dans le forum C++
    Réponses: 8
    Dernier message: 15/01/2013, 22h43
  2. SWAP IDIOM COPY CONSTRUCTOR
    Par guillaume07 dans le forum C++
    Réponses: 32
    Dernier message: 01/06/2010, 07h49
  3. copy constructor/ assignement/ destructor
    Par lafrankette dans le forum Débuter
    Réponses: 5
    Dernier message: 24/08/2009, 18h09
  4. [debutant]probleme avec le copy constructor
    Par Battosaiii dans le forum Débuter
    Réponses: 10
    Dernier message: 09/11/2005, 10h33
  5. Copy constructor ?
    Par Keyser dans le forum MFC
    Réponses: 4
    Dernier message: 17/02/2004, 15h33

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