2010-06-24 5 views
1

J'ai une variable qui est la tête d'une liste liée. Je veux le faire const car il ne devrait jamais être changé, la variable est utilisée tout au long du programme, donc j'ai pensé que je devrais en faire un const global. Le problème est que je ne pouvais pas l'initialiser après que je l'ai déclaré const.comment initialiser un pointeur const global?

Comment puis-je contourner ce problème?

typedef struct PT { 
int x; 
int y; 
struct PT *next; 
} POINT; 

//globals 
POINT * const mypoint_head; 

int main(int argc, char *argv[]) 
{ 
    int size = 100; 
    mypoint_head= InitPoint(size); // error C2166: l-value specifies const object 
    //rest of code 

} 


POINT* InitPoint(int size) 
{ 
    POINT *tmp; 
    POINT *orig; 
    int a = 10; 
    int b = 1000; 
    orig = (POINT*) malloc (sizeof(POINT) * size); 
    if(orig == NULL) 
     return NULL; 

    tmp = orig; 
    for (i = 0; i < size; i++) 
    { 
     tmp->x = a++; 
     tmp->y = b++; 
     if (i == size -1) { 
      tmp->next = NULL: 
     } 
     else { 
      tmp->next = tmp+1; 
     } 
     tmp++; 
    } 
    return orig; 
} 
+1

Quel est l'avantage d'une tête de const ptr quand vous pouvez modifier le reste de la liste? C'est comme ajouter une porte de fer à une paillote. –

+0

@Amardeep: Je pense que c'est plus comme écrire l'adresse de quelqu'un à l'encre, plutôt qu'au crayon. Différentes personnes peuvent entrer et sortir, mais la maison est toujours au même endroit (sauf si vous habitez au Kentucky). –

+0

@Amardeep @Tim Schaeffer - oui Tim, mon intention était d'empêcher de changer mon pointeur "tête" et d'être incapable de libérer cette mémoire plus tard, la fuite ... y at-il une meilleure façon de faire cela? ou est-ce aussi simple que ... si c'est la "tête" ne le change pas. J'avais un nom différent et je l'ai accidentellement changé dans une autre fonction, jusqu'à ce que je réalise que je ne voulais pas faire ça. – emge

Répondre

0

Supprimer le qualificatif const de la déclaration globale et déclarer rest_of_code comme une fonction qui prend la version const-qualifiée du pointeur.

//globals 
POINT * mypoint_head; 

void rest_of_code(POINT* const mypoint_head) 
{ 
    mypoint_head = NULL; // this errors out now 
} 
int main(int argc, char *argv[]) 
{ 
    int size = 100; 
    mypoint_head= InitPoint(size); // no longer errors out 
    //rest of code 
    rest_of_code(mypoint_head); 
} 

+0

pourquoi voudrais-je avoir des fonctions prenant un paramètre global? Cela ne va-t-il pas à l'encontre du but d'être global? D'un autre côté, je ne pourrais pas en faire un global et utiliser votre stratégie ... quelle est la meilleure façon de gérer les "têtes" de la liste chaînée afin qu'elles ne soient pas modifiées par accident, et que la mémoire soit perdue? – emge

+1

Err, peut-être au lieu de marquer la tête comme const vous devriez fournir des fonctions pour la manipulation de la liste et accéder uniquement à la liste via ces fonctions. – ninjalj

+1

@ emge- Si vous craignez de perdre la tête d'une liste et de perdre de la mémoire, déclarez le nœud principal de façon statique et déclarez le reste de la liste de façon dynamique. De cette façon, le nœud principal ne peut pas être "perdu". – bta

3

Vous ne pouvez pas - c'est tout le point de const.

0

Vous devez utiliser un initialiseur dans la déclaration:

static POINT mypoint_data[100]; 
POINT * const mypoint_head = &mypoint_head; 

changer ensuite votre fonction InitPoint de prendre un pointeur vers la DataSpace au lieu d'appeler malloc et passer mypoint_data

Vous pouvez aussi coller extern POINT * const mypoint_head; dans un fichier d'en-tête de sorte qu'il est accessible dans d'autres unités de compilation.

0

(suppose c) const doivent être initialisées quand ils sont déclarés et ils ne peuvent pas être évalués. Peut-être que vous pourriez utiliser un pointeur const et le faire pointer vers votre tête et l'exposer au reste du code. Si je dois atteins peut être je vais exposer la variable par une fonction getListHead() et lui donner un nom obscur :)

merveilles ce que le cas d'utilisation est cependant. Je ferais fonctionner ma liste même si son pointeur de tête change. (si j'ai une tête de const, si je dois supprimer le noeud de tête je devrai déplacer les éléments comme dans un tableau)

1

Vous avez raison car la variable déclarée const ne peut jamais être changée. Malheureusement, votre ligne mypoint_head= InitPoint(size); compte pour essayer de changer la variable. Vous devez initialiser la variable const avec une valeur lorsqu'elle est déclarée.

Essayez quelque chose comme ceci:

//globals 
static POINT head_of_list; 
POINT* const mypoint_head = &head_of_list; 

Maintenant, vous pouvez initialiser la liste à l'aide:

mypoint_head->next= InitPoint(size-1); 

L'objet tête de liste a été déclarée statiquement, de sorte qu'il existe et que vous avez toujours eill besoin d'ajuster vos paramètres InitPoint de manière appropriée. Vous pouvez également avoir une référence extern au pointeur dans un autre fichier sans avoir à rendre l'objet qu'il pointe directement accessible (pour ce que ça vaut).

+0

merci bta ... J'aime vraiment votre solution, mais j'ai choisi une autre implémentation pour deux raisons A) Je ne voulais pas mélanger les éléments statiques et dynamiques B) Je ne voulais pas avoir à changer les arguments à InitPoint – emge

+0

La partie 'static' est purement optionnelle; ça marchera dans les deux cas. – bta

1

Personne n'a suggéré ce encore:

int main(int argc, char *argv[]) 
{ 
    int size = 100; 

    // cast address of mypoint_head to a non-const pointer: 
    POINT ** nc_pmh = (POINT **)&mypoint_head; 
    // use the address to set mypoint_head: 
    (*nc_pmh) = InitPoint(size); 
    //rest of code 
} 

Cela peut ne pas fonctionner en C++, où il ne peut pas vraiment fournir l'espace pour les objets const.

BTW: Ce n'est généralement pas une bonne pratique. Dans ce cas, cependant, cela fonctionne bien.BTW: vous voulez vérifier le retour de InitPoint(), et agir en conséquence (appelez exit(), probablement).

+0

merci Tim, j'apprécie votre solution intelligente. – emge

1

n'a pas de pointeur global const comme interface pour tout le reste.

utiliser une fonction: -

static POINT * mypoint_head; 

POINT* point_head() 
{ 
    return mypoint_head; 
} 
+0

... ou si vous pouvez accepter les macros: POINT * point_head_get() {return mypoint_head;} ​​#define point_head point_head_get() Voici comment stdout est défini dans mingw. – user877329

0

Je ne peux pas croire que personne n'a encore suggéré const_cast .. Il fonctionne aussi bien pour les pointeurs constants.

const_cast<POINTER *>(mypoint_head) = InitPoint(size); 

Simple comme ça, pas de déclaration de variable supplémentaire, rien.

Questions connexes