[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
Je debute en C++ et je prends en main un code deja existant.
Les pointeurs sont pour l instant defini de maniere arbitraire avec une taille maximum bien superieure a nos besoins. J ai donc voulu faire une initialisation dynamique mais je m heurte a une difficulte car les informations sur les tailles des pointeurs ne sont pas disponibles dans le programme principal. Je souhaiterai donc faire cette initialisation dans le corp d une fonction secondaire mais malheureusement je ne peux pas en C++ passer en argument un pointeur non initialise. Pour l instant je m en sors en definisant des pointeurs globaux mais je voulais savoir s il y avait une solution plus raffinee?
La structure du code n est pas tres souple et je ne peux pas recuperer la taille des pointeurs en dehors de cette fonction.
Pour ceux qui auraient du mal a me suivre voila en code ce que je souhaiterai faire, fonction f1. Mais qui ne fonctionne pas.
Merci

// function declaration
double *f(void);
void f1(double *x);
void f2(void);


//global variable
double *pt2;


double *f(void)
{
static int j;
double *x = new double[20];
for (int i =0; i<20;++i)
x[i] = i*(j+1);
j =j+1;
cout <<"j="<<j<< "\n";
return(x);
}

void f1(double *x)
{
static int j;
// delete[] x;
x = new double[20];
for (int i =0; i<20;++i)
x[i] = i*(j+1);
j =j+1;

}

void f2(void)
{
static int j;
pt2 = new double[20];
for (int i =0; i<20;++i)
pt2[i] = i*(j+1);
j =j+1;

}



int main()
{
double pt1[1];
double *pt;
int n=0;
while (n<2) {
n +=1;
// pt=f();
// f1(pt1);
f2();

return(EXIT_SUCCESS);
}

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
1
Merci pom mais je ne m en sors pas pour autant. Je connais rien au vecteur et je ne peux pas utiliser une fonction
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
0
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 492 > emmanuel
18 mai 2005 à 10:28
Je comprend pas bien... un pointeur ca n'a pas de "dimension"
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 ?
0
emmanuel > emmanuel
18 mai 2005 à 10:41
C est que je debute. Je parle de pointeur mais en fait ce sont des tableaux. Mais je pensais que c etait un peu la meme chose en C++ alors j ai fait un raccourci de langage. J aurais pas du?
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);
}
0
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
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);
}
0
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...
0
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 492
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 :
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 ;-))
0
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.
0
emmanuel > pom
18 mai 2005 à 11:43
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.
0
pom > emmanuel
18 mai 2005 à 12:03
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;
}
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...
0
PS Ce n est pour l instant pas du dynamique mais moi j aimerais que ca le devienne...
Je suis trop ambitieux pour un debut?
0
pom > emmanuel
18 mai 2005 à 11:32
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
};
0
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 492 > pom
18 mai 2005 à 11:48
Tout afait d'accord avec Pom... et la ce sera du dynamique... pas d'utilisation de mémoire inutile...
0

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

Posez votre question
mamiemando Messages postés 33093 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 4 mai 2024 7 751
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
0
Kermitt31 Messages postés 3669 Date d'inscription jeudi 15 juillet 2004 Statut Contributeur Dernière intervention 8 août 2006 492
18 mai 2005 à 15:08
Clair, net et efficace !!! ;-)
0