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 :

std::vector<Objet> ou std::vector<Objet*>


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut std::vector<Objet> ou std::vector<Objet*>
    Bonjour tout le monde,

    Je n'arrive pas à voir d'inconvénient à utiliser le conteneur std::vector de la manière suivante:
    std::vector<Object>

    On peut modifier, supprimer, et lorsque le vecteur n'est plus utile (l'objet qui le contient est détruit), les données sont effacées.

    Est-ce que je loupe quelques choses?
    Si oui, dans quelle situation est-il préférable de stocker les pointeurs? (A part bien sûr pour un gain d'espace dans le cas où les mêmes objets Object doivent être stocker dans différentes classes).

    Merci d'avance.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Le principal intérêt : Si Object est une classe de base et que le vecteur doit stocker des instances de classes dérivées. (mais si les pointeurs possèdent les objets pointés, un vector<[unique/shared]_ptr<Object> > est souvent une meilleure solution).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  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
    Tout dépends de ce qu'est Object.

    D'abord il faut comprendre comment marche std::vector.

    En gros, en interne, il va détenir une array (crée sur la heap) d'objets tous d'un même type.
    Ce qui sous entends que si onfait grandir le vector de plus d'éléments qu'il ne peut contenir, il va devoir recréer une auttre array plus grande, puis copier son ancienne array dedans et enfin désallouer l'ancienne array.

    Donc, tout dépends si Object peut
    1. Etre contenu dans une array (de manière safe)
    2. Peut être copié (de manière safe)


    Pour 1., il faut que ton objet ne soit pas polymorphique, c'est à dire que Object ne dois pas être une classe de base. Si tu comptes avoir des classes qui héritent de Object et que tu veux les contenir dans ton vector, alors tu ne peux pas faire std::vector<Object> puisqu'en interne tu auras une array d'Object qui n'auraient pas les informations des sous-classes (voir problème de "slicing").

    Pour 2 il faut que Object soit copyable ou au moins constructible par copie.


    Pour résumer:

    1. Si Object est un type de base et que tu veux contenir tous les objets qui héritent de Object, utilise un "pointeur" (je vais y revenir).
    2. Si Object est copyable et copy-constructible, alors tu peux utiliser std::vector<Object> (voir "sémantique de valeur")
    3. Si Object est gros et que tu fais grossir ton vector souvent, tu vas avoir des copies massives de temps en temps et donc potentiellement des ralentissements. A prendre en compte dans l'équation.

    Pour le cas ou tu as Object qui est une classe de base, alors tu dois utiliser un pointeur, mais pas forcément un pointeur "nu". Si tu utilises un pointeur nu, tu dois faire le code nécessaire pour gérer la vie des objets, et c'est assez relou parceque tu dois avoir un chemin clair pour définir quand doit mourrir ces Object.
    Le moyen le plus simple c'est le passer par des smart pointers, qui sont justement des pointeurs (poru ceux de la STL) déterminant la condition pour déclencher la fin de vie d'un objet.

    On a std::unique_ptr (si tu utilises un compilateur récent du moins) qui est à utiliser si celui qui a le std::unique_ptr<Object> doit être le seul à avoir le droit de vie et de mort sur l'objet pointé.

    Ensuite std::shared_ptr à utiliser quand tu veux que tous les objets qui pointent vers ton Ojbect le maintiennent en vie, mais si plus personne ne pointe dessus il est détruit automatiquement.

    Enfin std::weak_ptr est utiliser avec std::shared_ptr pour "briser les cycles" c'est à dire quand tu as des objets qui se pointent les uns les autres via des std::shared_ptr (ils font des cycles) et donc sont impossible a détruire si on perds leurs références.

    Enfin bref dans ton cas alors le plus simple c'est de commencer par un std::vector< std::unique_ptr< Object > > si ton vecteur a le droit de vie et de mort sur ton Object, ou std::vector< std::shared_ptr< Object > > si le vecteur les maintiens en vie mais qu'a lextérieur d'autres objets doivent pouvoir maintenir les Object en vie tant qu'il sont utilisés meme si le vector est détruit ou vidé.

    Enfin si tu fais juste une liste de "références" vers des objets, juste pour les "noter quelque part", alors un std::vector<Object*> est tout à fait correcte. Il faut juste faire attention à ce que l'on soit sur que les pointeurs soient toujours valides. Si il n'y a aucun moyen de s'en assurer, alors on est certainement dans un cas de std::shared_ptr, ou alors le design global n'est pas tres bon ou pas très clair.

    Voilà un topo global, mais en fait c'est une question qui dépends énormément du contexte, de la volontée derrière la contention, etc.

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    En complément, pour la partie "copyable" et la sémantique de valeur : FAQ C++ : Quand est-ce qu'une classe a une sémantique de valeur ?

  5. #5
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci beaucoup pour vos réponses ultra-rapides!

    Je pense que je vais partir avec les shared_ptr (mais ceux de boost pour "préserver" des performances similaires entre mes différentes plateformes (Windows, Mac, Linux) ).

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

Discussions similaires

  1. std::vector semble ne pas utiliser std::move, pourquoi ?
    Par n0-sheep dans le forum SL & STL
    Réponses: 7
    Dernier message: 15/03/2014, 02h25
  2. Réponses: 4
    Dernier message: 04/06/2012, 16h19
  3. Objets dérivé de std::ostream et manipulateur
    Par Sub dans le forum SL & STL
    Réponses: 2
    Dernier message: 03/10/2007, 07h26
  4. Polymorphisme et objets stockés dans un vector
    Par sylverspoon dans le forum Langage
    Réponses: 5
    Dernier message: 25/05/2007, 22h43
  5. [Vector/ArrayList] Ajouter/Afficher un element de type objet specifique
    Par elbopha dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 16/10/2006, 09h37

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