2010-07-18 10 views
0

Très bien, vous avez été très utile avec ma dernière question, alors je vais essayer une autre. Il s'agit également de devoirs et même si le dernier était assez ancien, il a été soumis et attend d'être marqué. Donc, s'il y a quelque chose qui me mordra, ce sera probablement ce problème. J'ai obscurci les noms de classe et autres car il est toujours possible de soumettre la tâche (pour les autres étudiants).istream_iterator fuite de mémoire

J'ai une classe dont le seul membre est un pointeur vers un objet. Cette classe est construite pour exposer certaines opérations à partir du pointeur actuellement en cours - le Object *o_ qui est une classe de base à Object{1, 2, 3, ...}. Maintenant, je suis en mesure de faire ce qui suit sans fuites de mémoire ou de plantages.

std::vector<ObjectPtr> v; 
v.push_back(ObjectPtr(new Object1(..., ..., ...))); 
v.push_back(ObjectPtr(new Object2(..., ...))); 
v.push_back(ObjectPtr(new Object1(.., .., ..))); 

// Copy Constructor Ptr 
std::vector<ObjectPtr> v2(v); 
// Assignment Operator Ptr 
std::vector<ObjectPtr> v3; 
v3 = v2; 

Tout cela fonctionne, et il n'y a pas de fuite de mémoire. Mais si j'essaie de lire dans le contenu d'un fichier avec un istream_iterator<ObjectPtr> il commence à fuir. ObjectPtr est la seule classe gérant la mémoire dynamique et Object *o_ est définie sur NULL ou allouée par Object{1, 2, 3, ...}.

Le fichier à lire ressemble à ceci

 
Object1 
... 
... 
Object2 
... 
... 
Object1 
.. 
std::ifstream is("file.txt"); 
std::istream_iterator<ObjectPtr> in(is), end; 
for (; in != end; ++in) 
    cout << *in << "\n"; 

La fonction ami ObjectPtr utilisé pour lire ces valeurs ressemble

friend istream &operator>>(istream &is, ObjectPtr &op) { 
    std::string tmp; 
    while (std::getline(is, tmp)) { 
     if (tmp == "Object1") { 
      op.o_ = new Object1; 
      return is >> (Object1 &)*(op.o_); // Send it to operator>> for Object1 
     } 
     if (tmp == "Object2") { 
      op.o_ = new Object2; 
      return is >> (Object2 &)*(op.o_); 
     } 
     ... 
    } 
    return is; 
} 

Quelque part ici, il commence sur moi unicorning, et j'aimerais vraiment savoir pourquoi. En un mot - istream_iterator fuit la mémoire alors que le constructeur d'affectation et de copie fonctionne correctement, ce qui me porte à croire que les classes Object{1, 2, 3, 4, ..} sont construites correctement, et le problème doit être trouvé dans operator>>.

Répondre

2

Voici la première chose qui me vient à l'esprit. Je ne sais pas si c'est la question que vous êtes de chasse pour:

friend istream &operator>>(istream &is, ObjectPtr &op) { 
    std::string tmp; 
    while (std::getline(is, tmp)) { 
     if (tmp == "Object1") { 
      op.o_ = new Object1; 

Dans cette dernière ligne, ce qui se passe à l'ancienne valeur op.o? Rappelez-vous, le streaming dans un objet signifie diffuser dans un objet entièrement construit et vous devez faire attention aux anciennes données de l'objet. (C'est pourquoi préfèrent souvent constructeurs prendre std::istream. Pour les objets complexes qui SaFES l'initialisation d'un objet qui doit être changé dans le moment suivant.)

Est-ce que ObjectPtr ont un opérateur d'affectation ou d'une fonction de membre swap()? Si c'est le cas, il peut être plus simple d'implémenter l'opérateur d'entrée en construisant un nouvel objet et en l'assignant à/swap avec op.

+0

Oh, mec .. Vous avez fait ma journée - supprimer op.o_; Merci merci merci! – citizencane

+0

@citizencane: Notez que vous devez toujours faire attention à ce membre 'o' dans beaucoup d'autres endroits. Et à propos de l'affectation? Copie-construction? Vraiment, je préférerais implémenter 'operator >>()' en termes d'autres membres (comme je l'avais écrit dans ma réponse) plutôt que de dupliquer tout ce code en manipulant manuellement un objet alloué dynamiquement. – sbi

+0

En y réfléchissant à nouveau, je pourrais même séparer 'ObjectPtr' en deux classes, puisqu'il fait (au moins) deux choses: (A) il gère un objet alloué dynamiquement et (B) il sert de proxy pour traiter ce problème objet. Si vous séparez (A) en une classe de pointeurs intelligents appropriée, l'implémentation (B) devient beaucoup plus facile et plus propre. – sbi