Et il est preferable d'utiliser assez rapidement les auto_ptr et les shared_ptr qui permettent d'allegerla gestion de l'allocation dynamique de memoire
Et il est preferable d'utiliser assez rapidement les auto_ptr et les shared_ptr qui permettent d'allegerla gestion de l'allocation dynamique de memoire
Cours et ateliers d'initiation à la mosaique LesPierresArcEnCiel
Salut,
On pourrait répondre à toutes tes questions de la manière suivante:
De manière générale, il faut préférer la gestion "statique" (AKA sur la pile) de la mémoire d'un objet plutôt que sa gestion "dynamique" (AKA sur le tas).
Cela sous entend que, tant que tu peux faire autrement, tu ne devrais pas avoir recours aux pointeurs.
Le corollaire de cela est que tu devrais utiliser éventuellement les conteneurs de la STL si tu envisage de "regrouper" plusieurs membres d'un même type.
Les méthodes renvoyant un membre renvoyant alors une référence sur le membre en question (constante, ou non, en fonction des besoins)
Les exception à ces règles sont relativement simples:
- Si un membre d'une de tes classes doit survivre à la destruction de l'objet qui le contient
- Si le membre représente en réalité le "conteneur" alors que la classe représente le "contenu" (exemple: un membre Usine dans une classe Travailleur)
- Si le membre est du même type (ou d'une classe de base/dérivée) que la classe (exemple: un membre de type Noeud dans la classe... Noeud)
- Si tu dois pouvoir profiter du polymorphisme, avec les méthodes virtuelles et autres astuces
- Si un membre peut ne pas exister (à ne pas confondre avec "peut ne pas être initialisé), et que tu veux pouvoir en tester l'existence
alors, tu devra faire appel aux pointeurs, et vraisemblablement à l'allocation dynamique.
Les méthodes renvoyant ces membres renvoyant alors un pointeur vers ces membres (constant ou non selon les besoins)
A noter que, pour le premier cas, il peut s'avérer utile d'avoir une classe séparée dont la responsabilité sera, justement, de gérer les éléments alloués dynamiquement, et que dans le deuxième cas, le pointeur peut pointer vers un élément créé de manière "statique".
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Bizarre je croyais que c'était l'inverse :
FAQ C Qu'est ce que sont la pile et le tas ?
Envoyé par FAQ C
Linux > *
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
T'inquiètes pas t'es pas le seul
Pour répondre au choix sur pointeurs ou références que ce soit pour le passage des paramètres ou les attributs d'une classe, j'aime bien la règle de la FAQ Quand utiliser des références et quand utiliser des pointeurs
Vous me direz encore faut il savoir les différences qui existent entre un pointeur et une référence. Mais bon c'est quand même les fondamentaux en C++.Utilisez les références aussi souvent que possible, et les pointeurs quand vous le devez.
Linux > *
Disclaimer: Ami débutant en C++, tous les exemples de code de ce message sont faux, archi-faux. Ne viens pas me dire que tu n'étais pas prévenu.
Oui, mais pas trop vite : j'ai observé (ici) que certains commencent à utiliser shared_ptr avant d'avoir compris ce qu'est l'allocation dynamique, d'où des horreurs du type :
Le problème, AMA, est que shared_ptr est présenté comme la baguette magique qui fait qu'on n'a plus à s'embêter à comprendre l'allocation dynamique, et comme un GC intégré au langage (comme si avec les smart pointers C++ devenait Java); alors qu'au contraire, je ne vois pas comment on peut comprendre shared_ptr sans comprendre l'usage correct de delete.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 shared_ptr<A> p; A a; p.reset (&a);
Le discours : "laisser les shared_ptr gérer les désallocations tous seuls" peut, mal interprété, devenir "je n'ai plus à besoin de comprendre comment ça marche", et conduire à :
Comme quoi, l'absence de conversion implicite (A* -> shared_ptr<A> et shared_ptr<A> -> A*) n'effraie pas certains : ils invoquent plusieurs fonctions membres nommée, pour "convertir" shared_ptr<A> en A* en shared_ptr<A>. (Si ils voulaient "convertir" un A en B, et que la seule fonction qui renvoie un B et prennent A s'appelle A::I_want_to_get_a_B_and_then_die_an_horrible_death(), ils feraient b = a.I_want_to_get_a_B_and_then_die_an_horrible_death(). )
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 shared_ptr<A> p, q; p = blah blah; q.reset (q.get ());
Ca dépend de la durée de vie de l'instance créée. Si la durée de vie est celle du bloc en cours, la création d'une instance sur la pile suffira:
Si l'instance doit exécuter après que le bloc dans lequel est créée se termine, tu n'as pas le choix: il faut un pointeur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 void f() { // je n'ai besoin de l'instance de B que pendant l'exécution de f(): B b; // ... }
Bien évidemment, la vie n'est pas aussi simple. Dans certains cas, ce n'est pas l'instance qui est importante mais les valeurs qu'elles contient. Quoi qu'il en soit, la façon dont on créée une instance dépends de sa durée de vie.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 B* f() { // f() doit créer un objet B, et cet objet est utilisé par le programme // après que f() ait été exécuté : B* b = new B; // ... return b; }
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
Si j'ai :
Simple::i est au une gestion "statique" (AKA sur la pile) ou "dynamique" (AKA sur le tas)? Et pour Simple::s?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 struct Simple { int i; std::string s; };
En général, ça n'est pas une très bonne idée de renvoyer des références sur les membres d'une classe : ça brise l'encapsulation...
c'est une gestion statique (la gestion dynamique, c'est tout ce qui se joue avec des new, new[], delete, delete[]
Qui a bien pu aller te raconter celaEn général, ça n'est pas une très bonne idée de renvoyer des références sur les membres d'une classe : ça brise l'encapsulation...
Si, dans l'ensemble, tu a raison, il semble que tu oublie un concept très important: la const-correctness.
Tu ne peux pas forcément te passer de renvoyer un membre en tant que référence, pour la principale raison que si tu le passe en tant qu'objet, tu te payera la copie de ce membre - ce qui promet des joyeusetés sans fin s'il s'agit d'autre chose que des types primitifs, et surtout si ce sont des conteneurs de strctutres (ou pire: des conteneurs de pointeurs sur structure)...
Mais, si tu ne veux pas qu'un membre renvoyé en tant que référence soit modifié, tu n'as qu'à le renvoyer comme référence constante.
De cette manière, il existera un "contrat" entre toi et le compilateur selon lequel tu t'engage à ne pas aller modifier l'élément, et le compilateur grognera (il s'arrêtera sur une erreur d'ailleurs) si tu essaye de le faire
[EDIT] la particularité réside dans le fait de renvoyer une référence sur un type primitif.
Si tu ne les déclares pas comme référence, ils ne seront pas renvoyés en tant que telle (qu'elle soit constante ou non), ce qui fait que le membre ne sera pas modifié si on y chipote par la suite. (le code qui suit te le montrera )
Par contre, le compilateur refusera d'assigner la référence constante renvoyée par une méthode à une référence non constante, et t'interdira de modifier la référence constante comme l'indiquent les commentaires
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 #include <iostream> using namespace std; struct S { int i; S(int i=1):i(i){} const int& geti(){return i;} }; int main() { S s(10); int i=s.geti(); ++i; cout<<"i ="<<i<<endl; cout<<"s.i ="<<s.geti()<<endl; //s.i n'a pas été modifié //int &j=s.geti(); //NOK référence non constante const int& j=s.geti(); //OK j est une référence constante //j=15; //NOK: assignation la référence read-only 'j' return 0; }
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Je le fais tout le temps pour les matrices ou pour éviter des copies, donc ça dépend des cas.
Mon point de vue? Ce n'est pas un point de vue, c'est un fait.
Si tu renvoies une référence sur un membre :
alors tu révèles à tous les clients l'existence d'un membre de type T.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 class C { public: T& expose_impl(); private: T m; };
Tu caches son nom, la façon précise de l'allouer. Mais tu exposes son type. Si au départ T est un double, tu ne pourra pas le remplacer par float (disons, pour gagner de la place) sans changer la déclaration de expose_impl, donc l'interface publique de C.
Cette discussion a déjà eu lieu maintes fois sur le forum, ça serait sympa de ne pas recommencer. De plus, on a répondu à la question initiale, il me semble, donc on peut dire que cette même question est résolue.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager