2010-02-23 6 views
3

Je ne vais pas aller plus loin en allouant de la mémoire pour les tableaux en C et principalement en C++. J'ai cherché des exemples mais il n'y en a pas pour moi, du moins il me semble.C (++) confusion de malloc

Donc, si j'ai un typedef ici comme ceci:

typedef struct 
{ 
int x; 
int y; 
} Coordinate; 

Coordinate* myList; 

Et je un tableau du type Coordinate aussi, comment puis-je ajouter des articles à dynamiquement. Tout ce que je sais, c'est que je dois utiliser malloc et plus tard free en C et new/delete en C++. (Malloc fait peur l'enfer hors de moi)

donc ce que je visais une fonction comme ceci:

void AddSomething (int x, int y) 
{ 
// myList malloc/new magic here 
} 

Ma question est:

  • Comment fonctionne la ligne qui prévoit d'allouer nouvelle mémoire pour myList, puis ajoute le nouvel élément à ressembler? Pourriez-vous s'il vous plaît me montrer un de travail exemple pour C et C++?

  • Comment fonctionne exactement malloc en C? Il y a des choses à ce sujet que je ne connais pas bien (il y a une sorte de pointeur avant que la fonction, et la variable allouée est définie sur malloc de la valeur de retour)

+0

Voulez-vous allouer dynamiquement un tableau dont la longueur est fixée après l'allocation ou souhaitez-vous utiliser un tableau de longueur variable (c'est-à-dire une liste liée ou similaire)? En outre, il existe un monde de différence entre la façon dont vous le feriez en C ou en C++. C'est-à-dire, avec C++, vous pouvez simplement utiliser 'std :: vector' qui fera le plus gros du travail pour vous. –

+0

De plus, vous auriez idéalement un constructeur 'Coordinate :: Coordinate (int x, int y)' en C++. –

+1

Le typedef ne sert à rien ici. Il est sans rapport avec la question, et est grossier obfuscatory. Vous n'avez pas besoin d'un typedef pour définir une structure. –

Répondre

14

Utilisez vecteur pour faire le emploi.

#include <vector> 

typedef struct 
{ 
int x; 
int y; 
} Coordinate; 

std::vector<Coordinate> coordinates; 

Coordinate newCoord; 
newCoord.x = 1; 
newCoord.y = 1; 

coordinates.push_back(newCoord); 

Informations supplémentaires: Pour comprendre malloc/gratuit et nouveau/supprimer, vous pouvez lire le chapitre

13: Création d'un objet dynamique

dans Bruce Eckel Thinking C++ Volume 1. C'est un livre qui peut être téléchargé gratuitement.

3

Pour toute question comme celle-ci, la première réponse doit être une autre question. Plus précisément, y at-il une vraiment bonne raison pour laquelle vous ne pouvez pas utiliser un std::vector? Sauf si vous vraiment, vraiment, absolument ne peut pas, c'est la bonne chose à faire. Sinon, votre seul véritable choix est d'écrire (encore une fois) une imitation de std::vector. Bien que je ne vous connaisse pas personnellement, l'expérience indique que ce que vous écrivez ne sera probablement pas aussi bon.

0

C malloc alloue simplement de la mémoire, mais ne "construit" pas un objet. En C++, vous utiliseriez généralement new, qui alloue et construit l'objet. La principale différence est new appelle le constructeur après l'allocation de la RAM. malloc est juste un gestionnaire de mémoire «bête», mais peut mieux fonctionner dans certains cas spécifiques où vous avez besoin de mémoire brute non typée.

Les deux new et malloc "retournent" un pointeur. Un pointeur est une adresse.Donc, c'est la forme des deux, ce sont des expressions d'affectation.

Coordinate * notObject = (Coordinate*)malloc(sizeof(Coordinate)); 
Coordinate * object = new Coordinate(); 

Remarque, malloc retourne un void *, vous devez donc jeter. new est tapé, donc il n'y a pas de casting requis.

0
  • Comment la ligne qui alloue une nouvelle mémoire pour myList et ajoute le nouvel élément-il ressembler? Pourriez-vous s'il vous plaît me montrer un exemple de travail pour C et C++?

Il y a en fait deux options différentes: Vous pouvez créer un tableau de Coordinate objets à l'aide:

Coordinate *list = new Coordinate[ 42 ]; // list can hold at most 42 objects 

Ou, utilisez une liste chaînée, qui bien sûr vous avez besoin de changer la définition de votre Coordinate-type de données:

typedef Coordinate_t { 
    int x, y; 
    Coordinate_t *next; 
}; 

Insertion dans une liste, est un peu plus compliqué.

Bien sûr, si vous utilisez C, vous ne pouvez pas utiliser l'opérateur new, mais devront plutôt utiliser malloc:

Coordinate *list = malloc(*list * 42); /* list can hold at most 42 objects */ 
  • Comment fonctionne exactement malloc dans le travail de C? Il y a des choses à ce sujet que je ne connais pas bien (il y a une sorte de pointeur avant que la fonction, et la variable allouée est définie sur mallocs valeur de retour)

La fonction d'allocation utilise certains API spécifique au système d'exploitation pour demander de la mémoire au magasin libre (et par conséquent, cela dépend de l'implémentation). Exemple: Sur * nix, une API système appelée sbrk et des amis sont utilisés.

5

Pour C, ce qui suit va créer une liste contenant une seule coordonnée:

myList = malloc(sizeof(Coordinate)); 

Si vous souhaitez allouer un tableau de taille n, vous procédez comme suit:

myList = malloc(n * sizeof(Coordinate)); 

En C++ , le code d'un tableau de taille n ressemble à ceci:

myList = new Coordinate[n]; 

Pour le cas C++, votre classe doit avoir une valeur def constructeur ault, que la classe Coordinate a implicitement. Cependant, pour C++, je suggère fortement d'utiliser un std::vector<Coordinate> au lieu d'un tableau géré manuellement. En outre, vous pouvez également utiliser malloc() pour allouer de la mémoire en C++, mais il n'alloue que de la mémoire brute, tandis que l'utilisation de new déclenchera également un appel au (x) constructeur (s). Dans le cas de votre structure, il n'y a pas de différence puisqu'il s'agit d'une structure POD et ne nécessite pas de constructeur.Aussi, gardez à l'esprit que si vous allouez de la mémoire en C++ en utilisant malloc(), vous devez utiliser free() pour le libérer; Si vous utilisez new vous devez utiliser delete - le mélange des deux peut conduire à des résultats très intéressants qui ne sont pas amusants à déboguer. Avec new, vous devrez également vous assurer que vous correspondez au type d'appel correct. Tout ce qui a été créé en utilisant new doit être nettoyé avec delete et tout ce qui a été créé avec array new comme dans mon exemple ci-dessus doit être supprimé en utilisant delete[].

+2

N'oubliez pas d'utiliser 'delete []', pas seulement 'delete'! –

+2

Un 'void *' est correctement converti en n'importe quel type de pointeur d'objet sans un cast - en fait on ne devrait pas * cast * la valeur de retour de 'malloc' en C. J'écrirais ci-dessus comme myList = malloc (sizeof * myList) –

+0

@Fred Larson - merci pour le rappel, juste mis à jour la réponse –

1

Malloc fait peur l'enfer hors de moi

Se méfier de la main managed mémoire dynamique est une bonne idée --- il y a beaucoup de chances de faire des erreurs le faire; difficile de déboguer des erreurs --- mais pas besoin d'avoir peur.

Ce que malloc fait est demande au système d'exploitation pour un morceau de mémoire au moins CE grand. C'est tout. Vous devez utiliser des pointeurs pour garder une trace de celui-ci car le compilateur ne sait pas quelle mémoire le système d'exploitation choisira pour vous, et ne peut donc pas connecter un nom de variable à l'endroit au moment de la compilation.

Qu'est-ce que free fait est dire le système d'exploitation, je suis fait avec cette mémoire et ne sera pas l'utiliser à nouveau. C'est tout

Les new et delete de C++ appellent également des routines d'initialisation et de finalisation sous la forme du constructeur ou du destructeur approprié. Je ne vais pas dire "c'est tout" à ce sujet, car il ya quelques détails dans que affaires.

Ainsi, pour utiliser l'allocation dynamique, vous devez

  • Demandez la mémoire dont vous avez besoin avant vous essayez avec succès à l'utiliser, et vérifiez que vous avez réellement obtenu certains (le système d'exploitation pourrait dire « Non, ne peut pas l'avoir. "vous savez)
  • Assurez-vous de l'initialiser (soit écrire le bon constructeur en C++ ou le gérer vous-même en c)
  • Ne pas perdre le fil.
  • Assurez-vous de gérer tout nettoyage nécessaire avant de le rendre (destructeurs en C++, à la main en c). C'est probablement la partie la plus difficile de toute l'affaire.
  • Ne jamais utiliser la mémoire après que vous avez redonné
0
#include <stdlib.h> 

struct 
{ 
int x; 
int y; 
} Coordinate; 

Coordinate* myList = 0; 

int myListLength = 0; // initialize myListLength to size of myList 

void AddSomething (int x, int y) 
{ 
    int i; 
    // malloc returns a void pointer, so we cast it to be a Coordinate * 
    Coordinate* newList = (Coordinate*)malloc(sizeof(Coordinate)*(myListLength+1)); 
    for(i=0; i < myListLength; ++i) { 
     newList[i] = myList[i]; 
    } 
    newList[myListLength].x = x; 
    newList[myListLength].y = y; 
    if(myList) 
     free(myList); 
    myList = newList; 
    ++myListLength; 
} 

Notez que c'est une bien meilleure idée d'utiliser std :: vector si vous le pouvez.