[C++] initialisation dynamique de pointeur
Fermé
Emmanuel
-
17 mai 2005 à 12:22
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 - 18 mai 2005 à 15:08
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 - 18 mai 2005 à 15:08
A voir également:
- [C++] initialisation dynamique de pointeur
- Tableau croisé dynamique - Guide
- Liste déroulante dynamique excel - Guide
- Pointeur souris disparu windows 10 - Guide
- Liste déroulante dynamique en cascade excel - Guide
- Erreur d'initialisation de l'application adobe reader ✓ - Forum Téléchargement
5 réponses
Salut, tout d'abord qq remarques :
n'écris pas double *pt; mais plutot double *pt=NULL;
tu as écrit :
double *f(void)
{
static int j;
double *x = new double[20];
for (int i =0; i<20;++i)
x[i] = i*(j+1); // que vaut j ? il n'est pas initialisé ?
j =j+1;
cout <<"j="<<j<< "\n";
return(x);
}
dans cette fonction, tu as crée un pointeur (cf double *x = new double[20];) mais tu ne l'effaces pas => fuite de mémoire !!
pour éviter les fuites de mémoire, dès que tu as un new, il faut que tu fasses un delete !!
ensuite, si tu veux des tableaux et redéfinir la taille, tu peux utiliser les std::vector avec un #include<vector>
par exemple :
std::vector<double> v(5);
v.size(); -> 5
sinon tu peux faire un truc du genre
void f(double x[]);
ou bien void f(double x[],unsigned int taille) // taille est la taille de ton tableau x
n'écris pas double *pt; mais plutot double *pt=NULL;
tu as écrit :
double *f(void)
{
static int j;
double *x = new double[20];
for (int i =0; i<20;++i)
x[i] = i*(j+1); // que vaut j ? il n'est pas initialisé ?
j =j+1;
cout <<"j="<<j<< "\n";
return(x);
}
dans cette fonction, tu as crée un pointeur (cf double *x = new double[20];) mais tu ne l'effaces pas => fuite de mémoire !!
pour éviter les fuites de mémoire, dès que tu as un new, il faut que tu fasses un delete !!
ensuite, si tu veux des tableaux et redéfinir la taille, tu peux utiliser les std::vector avec un #include<vector>
par exemple :
std::vector<double> v(5);
v.size(); -> 5
sinon tu peux faire un truc du genre
void f(double x[]);
ou bien void f(double x[],unsigned int taille) // taille est la taille de ton tableau x
mamiemando
Messages postés
33446
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
20 décembre 2024
7 811
18 mai 2005 à 10:36
18 mai 2005 à 10:36
Bon petit topo sur les pointeurs ce qui te permettra d'y voir plus clair.
Un pointeur est une adresse, donc un truc codé sur quelques octets. Si tu ne l'initialise pas, il contient une adresse bidon. Donc oui tu peux créer un pointeur sans l'initialiser, mais dès que tu l'utiliseras, l'adresse étant foireuse, tu auras une erreur de segmentation.
Le rôle de l'allocation est de reserver une plage mémoire d'une taille que tu précise, et de retourner cette adresse pour ton pointeur. C'est classiquement ce que te retourne un "new" en c++ ou un malloc/calloc en C. A partir du moment ou ton pointeur est initialisé, tu fais tout ce que tu veux dans la plage mémoire que tu as reservé.
Ensuite dans l'état actuel des choses je ne trouve pas que tu allloues trop (tes boucles for allant jusqu'à 20 il est normal que tu alloues 20 !). Maintenant si c'est le 20 en question le problème, pourquoi ne pas simplement rajouter un paramètre ?
Exemple :
double *f(void,unsigned int const n)
{
static int j;
double *x = new double[n];
for (int i =0; i<n;++i)
x[i] = i*(j+1); // que vaut j ? il n'est pas initialisé ?
j =j+1;
cout <<"j="<<j<< "\n";
return(x);
}
Un pointeur est une adresse, donc un truc codé sur quelques octets. Si tu ne l'initialise pas, il contient une adresse bidon. Donc oui tu peux créer un pointeur sans l'initialiser, mais dès que tu l'utiliseras, l'adresse étant foireuse, tu auras une erreur de segmentation.
Le rôle de l'allocation est de reserver une plage mémoire d'une taille que tu précise, et de retourner cette adresse pour ton pointeur. C'est classiquement ce que te retourne un "new" en c++ ou un malloc/calloc en C. A partir du moment ou ton pointeur est initialisé, tu fais tout ce que tu veux dans la plage mémoire que tu as reservé.
Ensuite dans l'état actuel des choses je ne trouve pas que tu allloues trop (tes boucles for allant jusqu'à 20 il est normal que tu alloues 20 !). Maintenant si c'est le 20 en question le problème, pourquoi ne pas simplement rajouter un paramètre ?
Exemple :
double *f(void,unsigned int const n)
{
static int j;
double *x = new double[n];
for (int i =0; i<n;++i)
x[i] = i*(j+1); // que vaut j ? il n'est pas initialisé ?
j =j+1;
cout <<"j="<<j<< "\n";
return(x);
}
Encore merci
je crois que je n avais pas etre tres clair au depart mais ca se precise.
Dans mon exemple, j ai mis 20 comme j aurai pu mettre landa. Dans le code, les tableaux sont par defaut 99*999... Le truc c est que je ne peux pour l instant pas utiliser de return(x) parce que ma fonction f est une fonction void f(...) qui alloue dans la realite de mon code plein de pointeurs et je ne me voyais pas la scinder en une fonction par pointeurs alloues...
Y a une solution?
Je suis un peu plus clair? Desole...
je crois que je n avais pas etre tres clair au depart mais ca se precise.
Dans mon exemple, j ai mis 20 comme j aurai pu mettre landa. Dans le code, les tableaux sont par defaut 99*999... Le truc c est que je ne peux pour l instant pas utiliser de return(x) parce que ma fonction f est une fonction void f(...) qui alloue dans la realite de mon code plein de pointeurs et je ne me voyais pas la scinder en une fonction par pointeurs alloues...
Y a une solution?
Je suis un peu plus clair? Desole...
Kermitt31
Messages postés
3669
Date d'inscription
jeudi 15 juillet 2004
Statut
Contributeur
Dernière intervention
8 août 2006
495
18 mai 2005 à 11:04
18 mai 2005 à 11:04
C'est pas de l'allocation dynamique que tu fais la... tu continues de faire tableau[nb_colonnes]... ca c'est pas de l'allocation dynamique, c'est du statique ! Dans l'allocation dynamique, tu alloues au fur et à mesure que tu as besoin de stocker un nouvel element.
le mieux c'est de definir une structure qui va représenter le type d'info que tu veux stocker dans ton tableau dynamique. Cette structure va en plus contenir un pointeur qui pointera vers la donnée suivante.
Au depart, tu créé un élément et le pointeur ne pointe sur rien (tu le mets a null). quand t veux ajouter un element, tu le créer (tu mets l'adresse du pointeur de sa structure a null) et tu affectes l'adresse de la structure que tu viens de créer au pointeur de la structure précédente... je sais pas si c'est tres clair !!!
au départ tu as :
quand tu veux ajouter une donnée :
désolé c'est un peu moche comme dessin mais j'ai pas trouvé mieux ;-))
le mieux c'est de definir une structure qui va représenter le type d'info que tu veux stocker dans ton tableau dynamique. Cette structure va en plus contenir un pointeur qui pointera vers la donnée suivante.
Au depart, tu créé un élément et le pointeur ne pointe sur rien (tu le mets a null). quand t veux ajouter un element, tu le créer (tu mets l'adresse du pointeur de sa structure a null) et tu affectes l'adresse de la structure que tu viens de créer au pointeur de la structure précédente... je sais pas si c'est tres clair !!!
au départ tu as :
structure1 : - donnée1 - pointeur = null
quand tu veux ajouter une donnée :
structure1 : - donnée1 --<-- pointeur | | | -> structure2: - données2 - pointeur = null
désolé c'est un peu moche comme dessin mais j'ai pas trouvé mieux ;-))
Salut, si j'ai bien compris le message de Kermitt31, il te propose de faire des listes chaînées.
Je dois sûrement être un peu long à bien saisir ton problème, mais veux-tu initialiser un tableau sans connaitre sa dimension ? En sachant qu'il faut que fasses ceci dynamiquement (donc avec des pointeurs) ?
si tu le faisais en statique, utilies les std::vector. Tu auras ainsi acces au resize(), reserve(), push_back() etc etc...
Si tu dois (ai-je bien compris) initialiser un tableau sans connaitre sa dimension (ca me parait bizarre tout de même), soit tu utilises les listes chainees (soit tu te les codes soit tu utilises les std::list où tout est déjà fait) comme t'as dit Kermitt31, soit tu te fais un tableau de taille gigantesque puis tu le "coupe" (cad tu recopies tous les éléments dont tu as besoin dans un autre tableau de taille plus petite puis tu effaces le grand tableau à l'aide d'un delete [])
J'espère avoir bien saisi ton problème.
Je dois sûrement être un peu long à bien saisir ton problème, mais veux-tu initialiser un tableau sans connaitre sa dimension ? En sachant qu'il faut que fasses ceci dynamiquement (donc avec des pointeurs) ?
si tu le faisais en statique, utilies les std::vector. Tu auras ainsi acces au resize(), reserve(), push_back() etc etc...
Si tu dois (ai-je bien compris) initialiser un tableau sans connaitre sa dimension (ca me parait bizarre tout de même), soit tu utilises les listes chainees (soit tu te les codes soit tu utilises les std::list où tout est déjà fait) comme t'as dit Kermitt31, soit tu te fais un tableau de taille gigantesque puis tu le "coupe" (cad tu recopies tous les éléments dont tu as besoin dans un autre tableau de taille plus petite puis tu effaces le grand tableau à l'aide d'un delete [])
J'espère avoir bien saisi ton problème.
tu as bien saisi mon probleme.
Le truc c est que comme on n arrive pas a passer les tableaux en arguments avant leur allocation, on les surdimensionne et apres on se contente de remplir les "cases" reelement necessaires.
Mais ta proposition de couper le tableau me plait. C est dans mes cordes. Je garde les listes chainees pour la semaine prochaine.
J aurai mis le temps mais j ai appris plein de choses.
Merci a tous.
Le truc c est que comme on n arrive pas a passer les tableaux en arguments avant leur allocation, on les surdimensionne et apres on se contente de remplir les "cases" reelement necessaires.
Mais ta proposition de couper le tableau me plait. C est dans mes cordes. Je garde les listes chainees pour la semaine prochaine.
J aurai mis le temps mais j ai appris plein de choses.
Merci a tous.
Re-salut, tu veux qqch comme ca ?
#include<iostream>
using std::cout;
using std::endl;
double * f(double * tab)
{
if(tab!=NULL)
{
delete [] tab;
double * tab=NULL;
}
const int n=5; // la taille du tableau
tab=new double[n];
for(int i=0;i<n;i++) tab[i]=i;
return tab;
}
int main()
{
double * tab=NULL;
tab=f(tab);
for(int i=0;i<5;i++) cout<<tab[i]<<endl;
delete [] tab;
return 0;
}
#include<iostream>
using std::cout;
using std::endl;
double * f(double * tab)
{
if(tab!=NULL)
{
delete [] tab;
double * tab=NULL;
}
const int n=5; // la taille du tableau
tab=new double[n];
for(int i=0;i<n;i++) tab[i]=i;
return tab;
}
int main()
{
double * tab=NULL;
tab=f(tab);
for(int i=0;i<5;i++) cout<<tab[i]<<endl;
delete [] tab;
return 0;
}
en gros si je comprends bien une structure, c est un pointeur dont les adresses des differents elements pointes ne se suivent pas et qui n a pas de taille definie?
Je crois qu il va falloir que je me plonge dans le chap suivant de mon bouquin de C++ car pour l instant, j avoue que les structure ne me parlent pas. C est meme pas dans l index... C est des classes en anglais?
Pfff, j apprends...
Je crois qu il va falloir que je me plonge dans le chap suivant de mon bouquin de C++ car pour l instant, j avoue que les structure ne me parlent pas. C est meme pas dans l index... C est des classes en anglais?
Pfff, j apprends...
Salut, les listes chainées sont très bien pour apprendre le fonctionnement des pointeus, mais si tu dois intégrer ceci dans un prgm, utilises ce qui est déjà fait.
Les listes chaineées seraient qqch du genre
struct Case;
struct Case
{
int donnees;
Case * pCase; // un pointeur qui pointe vers une autre Case
};
Les listes chaineées seraient qqch du genre
struct Case;
struct Case
{
int donnees;
Case * pCase; // un pointeur qui pointe vers une autre Case
};
Kermitt31
Messages postés
3669
Date d'inscription
jeudi 15 juillet 2004
Statut
Contributeur
Dernière intervention
8 août 2006
495
>
pom
18 mai 2005 à 11:48
18 mai 2005 à 11:48
Tout afait d'accord avec Pom... et la ce sera du dynamique... pas d'utilisation de mémoire inutile...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
mamiemando
Messages postés
33446
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
20 décembre 2024
7 811
18 mai 2005 à 14:44
18 mai 2005 à 14:44
Une structure c'est tout con. Tu définis une sorte de container qui contient les information caractérisant un objet (en C on utilise des struct et en C++ on utilise plutôt des classes). Ainsi tu fais concorder ta structure de sorte à coller le plus possible avec ce que tu définis :
Exemple :
struct voiture{
unsigned int puissance;
char *marque;
char *couleur;
};
Mais attention, un pointeur et une structure ça n'a rien à voir. Un pointeur est une notion très générale, c'est une adresse d'un "quelque chose" (un entier, une structure, une classe, un tableau....).
Le pointeur le plus générique est "void *" mais en général on spécifie ce qui est pointé : par exemple si tu pointe sur un entier : int*, sur un struct voiture : struct voiture *,...
Si tu veux allouer dynamiquement un tableau, il ne faut pas utiliser le fameux [] qui consite en fait allouer une plage contigue de mémoire (par exemple int t[3] allouera une zone recouvrant trois entiers).
En C tu peux utiliser les listes chainées (cf post precédant avec les struct Maillon) mais en C++ tu as des containers tout prêts (cf C++ STL) :
- set : ensemble triés d'éléments unique, accès à l'élément par dichotomie.
- vector : le plus simple, un tableau que tu remplis à coup de push_back
- ...
Pour plus d'infos sur la STL :
http://etna.int-evry.fr/COURS/C++/CoursEA/node39.html
http://www.cppreference.com/cppstl.html
http://c.developpez.com/faq/cpp/?page=STL
Bonne chance
Exemple :
struct voiture{
unsigned int puissance;
char *marque;
char *couleur;
};
Mais attention, un pointeur et une structure ça n'a rien à voir. Un pointeur est une notion très générale, c'est une adresse d'un "quelque chose" (un entier, une structure, une classe, un tableau....).
Le pointeur le plus générique est "void *" mais en général on spécifie ce qui est pointé : par exemple si tu pointe sur un entier : int*, sur un struct voiture : struct voiture *,...
Si tu veux allouer dynamiquement un tableau, il ne faut pas utiliser le fameux [] qui consite en fait allouer une plage contigue de mémoire (par exemple int t[3] allouera une zone recouvrant trois entiers).
En C tu peux utiliser les listes chainées (cf post precédant avec les struct Maillon) mais en C++ tu as des containers tout prêts (cf C++ STL) :
- set : ensemble triés d'éléments unique, accès à l'élément par dichotomie.
- vector : le plus simple, un tableau que tu remplis à coup de push_back
- ...
Pour plus d'infos sur la STL :
http://etna.int-evry.fr/COURS/C++/CoursEA/node39.html
http://www.cppreference.com/cppstl.html
http://c.developpez.com/faq/cpp/?page=STL
Bonne chance
Kermitt31
Messages postés
3669
Date d'inscription
jeudi 15 juillet 2004
Statut
Contributeur
Dernière intervention
8 août 2006
495
18 mai 2005 à 15:08
18 mai 2005 à 15:08
Clair, net et efficace !!! ;-)
18 mai 2005 à 10:22
void f(double x[]);
ou bien void f(double x[],unsigned int taille) // taille est la taille de ton tableau x
si mon pointeur n est pas deja dimensionne. Le programme compile mais erreur a l execution.
Je voudrais en fait tout simplement passer en argument un pointeur non dimensionne. Est ce possible?
Sinon avec static int j; pas besoin d initialisation par defaut mis a 0 et la variable garde sa valeur d un appel a l autre.
Manu
18 mai 2005 à 10:28
Un pointeur ca pointe vers une case memoire que tu as reservé avant... Je pense que quand tu parles de dimension, tu parles de la case memoire pointée !?!
Ca me semble pas tres propre ton code...
Ou est ce que ca croute a l'execution ?
18 mai 2005 à 10:41
Et il faut quand meme reserve de la place la ou le pointeur va pointer, non? Le truc c est qu au moment ou j appelle ma fonction je ne sais pas encore quelle sera la dimension de mon tableau.
Le message d erreur est en allemand.. arg et je suis incapable de le traduire... Je debute aussi.
Die Anweisung in "*00401717" verweist auf Speicher in "0*00000004". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden.
Merci
Le code epuree ressemble a ca
// function declaration
void f1(double *x);
void f2(void);
//global variable
double *pt2;
void f1(double x[]) //initialisation du tableau
{
x = new double[20];
for (int i =0; i<20;++i)
x[i] = i;
}
void f2(void) // variable global
{
pt2 = new double[20];
for (int i =0; i<20;++i)
pt2[i] = i;
}
int main()
{
double *pt1=NULL;
int n=0;
n +=1;
f1(pt1);
f2();
for (int i =0; i<20;++i)
cout <<"pt1["<< i << "]= " << pt1[i] << "\npt2["<< i << "]= " << pt2[i] << "\n";
return(EXIT_SUCCESS);
}