CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C++] std::vector et pointeurs

Caudheur
Caudheur
Niveau 8
10 août 2012 à 08:04:59

Bonjour à tous,

Je fais appel à votre expertise.
J'ai besoin d'un vector pour contenir des objets, mais j'aimerais qu'à chaque push_back, les objets qu'ils contient ne soient pas détruits.

J'ai donc pensé à faire un vector de pointeur sur ces objets, de sorte que le resize du vector n'entraîne pas leur destruction.

Est ce une bonne idée ? J'ai lu sur developpez.com que faire un vector de pointeurs était redondant (le vector gérant lui même l'allocation dynamique en coulisse).

Merci d'avance :-)

Paulop
Paulop
Niveau 12
10 août 2012 à 09:54:41

"(le vector gérant lui même l'allocation dynamique en coulisse)."

Non, le vector se charge lui même de l'allocation dynamique de son array interne, mais ils n'alloue pas ce qu'on lui push.

Quand tu push dans un vector, il fait une copie de l'objet.

En general on utilise un vector de pointeurs quand on ne peut pas copier/se permettre de copier les objets.

Caudheur
Caudheur
Niveau 8
10 août 2012 à 10:14:58

D'accord, donc ça pourrait m'éviter d'utiliser un constructeur par copie pour les objets contenus ?

chris_27
chris_27
Niveau 10
10 août 2012 à 10:25:17

Bonjour,

Si tu utilises un std::vector<MonObjet*>, la classe vector se contentera (par défaut) de gérer la place nécessaire pour stocker des MonObjet*. En revanche, il n'y aura pas d'appel ni aux constructeurs de MonObjet, ni à son destructeur (alors qu'il n'y a "que" ça avec un std::vector<MonObjet>).

Caudheur
Caudheur
Niveau 8
10 août 2012 à 10:35:25

Ok, merci pour l'éclairage.
Pour manier des objets lourds ou pénibles à copier, je peux donc faire
vecteur.push_back(new Objet());
?

chris_27
chris_27
Niveau 10
10 août 2012 à 11:46:03

Par exemple, oui.

Après, n'oublie pas qu'il faudra faire un delete un jour. :-)))

Caudheur
Caudheur
Niveau 8
10 août 2012 à 12:02:59

Héhé, ça ferait une belle fuite mémoire :-)

Comme j'imagine qu'un simple vecteur.clear() ne ferra que mettre à zéro les pointeurs, je parcours le vecteur pour delete un à un ses objets.

Merci pour les précisions (^o^)/

Paulop
Paulop
Niveau 12
10 août 2012 à 12:10:53

Oui iterator et delete sur chaque objet, et après à la fin tu clear.

hyrulink2
hyrulink2
Niveau 7
10 août 2012 à 12:26:49

As-tu absolument besoin d'un vector? Si tu as juste besoin d’itérer, utilise un std::list, c'est en général une mauvaise idée d'utiliser un vector si on appelle souvent push_back.

Si tu a besoin de l'indexation en temps constant mais que tu n'a pas a tout prix besoin que les éléments soient stockés de manière contigus, pense à utiliser un std::deque: à la différence du vector, le push_back du deque ne réalloue pas de mémoire pour les objets précédemment insérés. Ca t'évitera les pointeur. Un seul désavantage: l'indexation est un poil plus lente.

Si tu est en C++11, pour éviter la recopie inutile lors du push_back, pense à la méthode emplace_back qui construit l'élement en place(elle existe aussi pour les vectors).

Enfin pense au smarts pointers du C++11 ou de boost(unique_ptr, shared_ptr et weak_ptr) si tu doit utiliser un vector pour ne pas t’embêter avec la mémoire, c'est un poil plus lent mais au moins il n'y a pas de leaks.

Caudheur
Caudheur
Niveau 8
10 août 2012 à 13:05:06

Merci pour tes suggestions hyrulink :)
J'avais essayé avec une std::list, mais les performances étaient un poil moins satisfaisante qu'avec les vecteurs (que je parcours à chaque frame).

Je ne connaissais pas cette propriété du std::deque, je vais m'y interesser, ça pourrait bien correspondre à mes besoins :-)

Ceci dit j'aime bien travailler avec des pointeurs, ça me donne une impression de souplesse et de légèreté lors du traitement des données.

chris_27
chris_27
Niveau 10
10 août 2012 à 14:00:29

« Ceci dit j'aime bien travailler avec des pointeurs, ça me donne une impression de souplesse et de légèreté lors du traitement des données. » :d) au détail près que le C++, c'est fait pour éviter les pointeurs justement. :(

hyrulink2
hyrulink2
Niveau 7
10 août 2012 à 14:15:42

Les pointeur donnent peut-être de la souplesse dans certains cas mais de la légèreté, surement pas.
C'est à la fois lourd au niveau du code, bien que les smarts pointers résolvent en partie le problème et egalement lourd niveau perfs: un new/delete c'est pas gratuit.

Caudheur
Caudheur
Niveau 8
10 août 2012 à 14:23:41

Chris : pourrais tu développer, ce genre de questions m’intéressent :)

Hyrulink : je rechigne pas mal à utiliser boost et/ou les smarts pointers pour l'instant !

chris_27
chris_27
Niveau 10
10 août 2012 à 15:53:40

Les pointeurs, c'est LE DÉMON ! (si tu ne me crois pas, passe dans mon bureau déboguer le code de mon projet qui hélas regorge de mauvais usages des pointeurs :sournois: ).
Partant de là, dès que tu peux faire sans pointeurs, fais sans pointeurs. :oui:

Le C++ t'offre pour ça trois choses qui remplacent bien des pointeurs :

1) les références.
Quand l'argument d'une fonction est gros, utilise un passage d'argument par référence (&), pas un passage par pointeur (*). De plus, si la fonction ne modifie par l'argument, utilise une référence constante (const&), ce qui améliore bien des choses en pratiques !

2) les objets.
De part leur nature, la gestion de la mémoire se fait dans les constructeurs et dans le destructeur. Si allouer de la mémoire est nécessaire, il y a des chances pour que tu es des pointeurs dans le code implantant ta classe. En revanche, le programme qui utilise le code ta classe est, lui, sans pointeurs.

3) les structures de données de la STL.
Souvent la solution pour stocker les données à manipuler tout au long du programme, ces structures masquent complétement les pointeurs sous-jacent (cf point 2).

Sinon, n'utilise pas boost. Ça t'apportera plus de soucis que de solutions. À ton niveau (enfin, c'est valable à tout niveau en fait), fais des choses simples. :-)

hyrulink2
hyrulink2
Niveau 7
10 août 2012 à 16:33:00

Par simple curiosité, qu'est ce que tu as contre boost, Chris?
Certes l'apprentissage demande un investissement de temps mais les tutos de boost sont bien expliqués et une fois qu'on a appris on gagne un temps monstre a éviter de recoder tout un tas de choses qui auraient du avoir leur place dans la bibliothèque standard.

Paulop
Paulop
Niveau 12
10 août 2012 à 17:03:47

J'ai une expérience de boost où j'arrivais pas à coder un truc, boost à apporté une solution, et au final, quelques mois plus tard je m’aperçois qu'une solution simple et sans boost existait, il suffisait de revoir la conception.

Du coup maintenant j'évite de base d'utiliser boost :hap:

godrik
godrik
Niveau 30
10 août 2012 à 17:45:07

Un des points important du C++ est RIAA. Ca veut dire "Ressource Acquisition Is Initialization". En bref, ca veut dire "N'alloue pas de memoire toi meme, BOWDEL!!" (Lisez sur wikipedia[1] si vous voulez des details). Quand une variable est initialise, elle doit obtenir sa memoire d'elle meme. Quand la variable disparait parceque son contenant est detruit (scope-out, deallocation memoire), elle doit relacher sa memoire.

C'est une des raisons pour laquelle std::vector est souvent preferer a faire une allocation manuellement. Ca rejoins le commentaire de hyrulink:

"Enfin pense au smarts pointers du C++11 ou de boost(unique_ptr, shared_ptr et weak_ptr) "

C'est un vrai bon conseil. Je ne suis pas fan de boost (c'est trop gros, c'est trop le bordel, la doc est pourri, certain module obscure son bugge a mort), mais les smart pointers sont vraiment pratique. En vrai, c'est classique de reimplementer les smart_pointers soi meme.

[1] http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

chris_27
chris_27
Niveau 10
10 août 2012 à 18:16:15

hyrulink2: c'est essentiellement du gros hack pour Gourou à poil long codant des choses obscures nécessitant précisément du gros hack. Dans la vraie vie, on n'a pas besoin de ça (surtout que le C++11 offre des alternatives dans le cas présent).

Caudheur
Caudheur
Niveau 8
11 août 2012 à 01:27:16

Un grand merci d'avoir pris la peine de m'expliquer. Je ne savais absolument pas que les pointeurs étaient à éviter !
Du coup je vais revoir mes habitudes de programmation, parce que se passer des pointeurs demande généralement de réviser la conception de l'appli.

Sous forums
  • Aide à l'achat Mac
  • Macintosh
  • Création de Jeux
  • Programmation
  • Création de sites web
  • Linux
  • Internet
  • Steam Deck
  • Hardware
La vidéo du moment