C++, variables dans la pile et le tas

Fermé
Wenzel - Modifié par Wenzel le 20/08/2011 à 17:57
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 - 21 août 2011 à 15:15
Bonjour,

J'aimerais avoir votre aide dans la compréhension du langage C++
J'ai déjà pas mal codé en Java et ma transition vers le C++ est rude.

Il y a plusieurs points qui me semblent flous dans le langage.

1 ) si j'ai bien compris, en Java, on déclare les types fondamentaux dans la pile, et on instancie les objets dans le tas ?

2) En C++, on peut faire ce qu'on veut, c'est à dire déclarer des types fondamentaux dans le tas via l'allocation dynamique de mémoire, ainsi que d'instancier des objets dans la pile ?

Dans ce cas, comment savoir, lorsque je crée une variable de classe, si elle devra se trouver dans le pile ou dans le tas ??

Autre chose, j'utilise le framework Qt.
Quelle est la différence entre faire

QList<Projet> listeDeProjet ; 
QList<Projet> *listeDeProjet; 
QList<Projet*> listeDeProjet 
QList<Projet*> *listeDeProjet;


Comment choisir entre toutes ces déclarations possibles de ma variable de classe listeDeProjet ??

Pour me repérer, j'ai crée un document de dessin ODG qui résume les schémas mémoire JAVA / C++
voici le Document en question.
https://docs.google.com/leaf?id=0BxGDwm2xs-VDZmNjMmJlYTQtYzNmOC00MGE0LTk4MDItNTIzZDg2ODUxYTll&hl=en_US

pourriez-vous m'indiquer les fautes ?

Merci beaucoup pour votre patience.

5 réponses

KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
20 août 2011 à 18:30
1) Java est un langage interprété, tout est géré par la machine virtuelle, ce n'est pas au développeur d'instancier la mémoire directement (a priori le ramasse-miette agit sur la pile)
2) Les allocations mémoire en C (malloc/free) et en C++ (new/delete) sont sur le tas.
3) Pour ton problème je pense que le template QList<T> nécessite que T soit une classe, en conséquence je pense que QList<Projet*> est incorrect. Par contre savoir si c'est listeProjet ou *listeProjet, je dirais peu importe, les deux sont corrects.
0
Merci KX.

Ma principale interrogation concerne la création des variables dans les classes.
En effet, (dîtes moi si je me trompe) En C, on avait besoin de l'allocation dynamique de mémoire pour conserver les variables dans le temps, puisqu'à la sortie d'une fonction, les variables locales sont détruites.

Sauf qu'en C++, on peut crée des classes.
Donc on a des attributs, qui, quoiqu'il arrive, ne seront jamais supprimés.
Donc pourquoi utiliser des pointeurs ?
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
20 août 2011 à 19:23
"En C, on avait besoin de l'allocation dynamique de mémoire pour conserver les variables dans le temps, puisqu'à la sortie d'une fonction, les variables locales sont détruites."
Non ! Tu peux utiliser des variables globales pour ça. Le problème c'est que la taille des données doivent être connues à la compilation, l'allocation dynamique (et donc les pointeurs) permet de stocker des données de tailles connues à l'exécution...

"En C++, on peut crée des classes. Donc on a des attributs, qui, quoiqu'il arrive, ne seront jamais supprimés."
Non ! De la même manière que tes variables locales, à la sortie de la fonction tes objets locaux seront détruits et leurs attributs supprimés !

Donc utiliser des pointeurs en C ou en C++ présentent les mêmes avantages et les mêmes inconvénients : ils permettent d'allouer de la mémoire qui n'est pas connue à l'exécution.
En effet dans les définitions de classe la taille des attributs doit être connue à l'avance !
0
D'accord,
donc lorsque je veux créer une variable, je me demande si je vais connaître sa taille à la compilation, ou bien à l'exécution.

Pour reprendre mon exemple avec ma liste de projet,

Vu que je ne peux pas connaître à l'avance la taille de ma liste (car tous les projets sont chargés pendant l'éxécution du programme), je vais devoir la déclarer en pointeur.
Donc Qlist * liste;

Mais pour ce qui est du type générique, je ne sais pas du tout comment rélféchir et prendre la meilleure décision.
entre QList<Projet> et QList<Projet*>
dans le premier cas, je fais une liste d'objets Projet, et dans le deuxième, je fais une liste de pointeurs, ce qui est radicalement différent.

une idée ?
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
Modifié par KX le 21/08/2011 à 12:37
Comme je l'ai dit hier, il me semble que QList<Projet*> soit incorrect, donc prends QList<Projet>
Quant à la taille dynamique de ta liste elle est normalement déjà gérée par l'objet QList, en fait utiliser un pointeur pour l'allocation dynamique n'aurait ici de sens que si tu ne savais pas de combien de listes tu aurais besoin ! Or dans ce cas tu pourrais t'en sortir avec des objets un peu plus complexes comme QList< QList<Projet> > ou d'autres classes STL ou Qt
0
OK, merci beaucoup.
J'ai une dernière question.
Lorsque j'écris une méthode qui doit faire un passage par référence,

je peux l'écrire
void f(Personnage *p) 

et
void f(Personnage& p)


Celà revient au même, mais y a t-il une façon meilleure qu'une autre ?
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
21 août 2011 à 13:20
Non cela ne revient pas du tout au même.
Le premier est le passage par pointeur, le second par référence.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
D'accord,
et si j'écris
Personnage *p = new Personnage();

dans le premier cas, je fais
f(p);

dans le second
f(*p);


Quelle écriture faut-il privilégier pour passer un argument ?
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
21 août 2011 à 15:15
Je pense que moins tu utiliseras de pointeur mieux c'est (surtout si tu ne sais pas t'en servir), mais ce n'est pas une question de savoir ce qu'il faut privilégier ou non, mais ce que tu dois faire.
Dans tes deux exemples, cela dépend des attributs de ta fonction f !

Si j'avais un contrôle absolu sur la classe Personnage et la fonction f, je ferais comme ceci :
void f(Personnage &perso) { ... }
Personnage p();
f(p);
0