Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6
  1. #1
    r0d
    r0d est actuellement connecté
    Expert Confirmé Sénior

    Profil pro
    Inscrit en
    août 2004
    Messages
    4 098
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : août 2004
    Messages : 4 098
    Points : 5 754
    Points
    5 754

    Par défaut vector et copy constructor

    Bonjour, prenons le code suivant:
    Code :
    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)?

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2012
    Messages
    574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Autre

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

    Informations forums :
    Inscription : février 2012
    Messages : 574
    Points : 1 346
    Points
    1 346

    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
    Expert Confirmé
    Avatar de Klaim
    Homme Profil pro Joel Lamotte
    Développeur de jeux vidéo
    Inscrit en
    août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Nom : Homme Joel Lamotte
    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 334
    Points
    3 334

    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 :
    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 actuellement connecté
    Expert Confirmé Sénior

    Profil pro
    Inscrit en
    août 2004
    Messages
    4 098
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : août 2004
    Messages : 4 098
    Points : 5 754
    Points
    5 754

    Par défaut

    Citation Envoyé par Klaim Voir le message
    En revanche, C++11 offre une solution.

    Code :
    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

  5. #5
    Membre habitué
    Inscrit en
    mars 2010
    Messages
    118
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 118
    Points : 134
    Points
    134

    Par défaut

    emplace_back prend un et un seul argument
    Heu, non, le prototype de emplace_back est le suivant :
    Code :
    1
    2
    template< class... Args >
    void emplace_back( Args&&... args );

  6. #6
    Membre Expert

    Inscrit en
    mai 2008
    Messages
    1 009
    Détails du profil
    Informations forums :
    Inscription : mai 2008
    Messages : 1 009
    Points : 2 199
    Points
    2 199

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •