Verkettete liste speicher freigeben?
-
bis auf conio.h und _getch, wo man lieber nen cin.get() verwenden sollte, ist doch alles C++
oder lieg ich jetzt falsch
-
Hallo Honky,
falsch im Sinne 'Speicher freigeben vergessen' hast Du meines Erachtens nicht gemacht. Nur das kann leicht passieren, wenn Du Dein Programm weiter ausbaust. Dein eigentlicher Fehler besteht darin, die Liste nicht vom Rest des Programms zu trennen. C++ bietet alles, was man dazu benötigt.
Ich zeige Dir mal, was ich meine:
#include <iostream> //#include <conio.h> using namespace std; struct Node // vorher List, weil das ist keine Liste, sondern nur ein Element einer Liste! { int data; Node *next; }; class List { public: List() : start( 0 ) // wie Zeile 15 usw. , lauf( 0 ) {} ~List() { // in Destruktor wird alles wieder freigegeben (vorher Zeilen 42-49) Node* l = start; while(l != 0) { cout << l->data << endl; Node* old = l; l = l->next; delete old; } } void push_back( int eingabe ) // push_back heißt hinten anfügen, also da wor lauf hinzeigt { // vorher Zeilen 24 bis 38 if( start == 0 ) { start = new Node; start->data = eingabe; start->next = 0; lauf = start; } else { lauf->next = new Node; lauf = lauf->next; lauf->data = eingabe; lauf->next = 0; } } private: Node* start; Node* lauf; // zeigt auf den letzten Knoten List& operator=( const List& ); // Kopieren kommt später List( const List& ); }; int main() { List list; int eingabe; do { cout << "Eingabe: "; cin >> eingabe; list.push_back( eingabe ); }while(eingabe != 0); cin.get(); return 0; } // mit Ende des Scopes wird der Destruktor von 'list' aufgerufen
Der Code macht das gleiche, wie vorher, nur Dein main() sieht jetzt schön aufgeräumt auf, und Du kannst dort weiteres integrieren, ohne Dich um die Innereien von 'List' kümmern zu müssen.
Den Code kann man noch mehr 'C++-like' machen, indem Du z.B. einen Konstruktor für die struct Node einführst.
struct Node // vorher List { Node( int d, Node* n ) : data( d ) , next( n ) {} int data; Node *next; };
dann vereinfacht sich u.a. push_back sofort zu
void push_back( int eingabe ) // push_back heißt hinten anfügen, also da wor lauf hinzeigt { // vorher Zeilen 24 bis 38 Node* n = new Node( eingabe, 0 ); if( start == 0 ) { start = n; } else { lauf->next = n; } lauf = n; }
.. außerdem hast Du nun keine Chance mehr, die Initialisierung der Variablen zu vergessen. D.h. Dein Programm wird robuster.
Weiterhin empfehle ich Dir for-Schleifen zu verwenden, statt while; denk' mal drüber nach.
Noch eine Schlussbemerkung: wenn Du den von Dir geposteten Code aus einem Buch hast, so lass die Finger davon. Du lernst da garantiert kein C++!
Gruß
Werner
-
BasicMan01 schrieb:
bis auf conio.h und _getch, wo man lieber nen cin.get() verwenden sollte, ist doch alles C++
oder lieg ich jetzt falsch
Ja und nein
Das Programm benutzt nur den C-Anteil von C++. Gerade für eine Liste würden sich aber die objektorientierten Bestandteile anbieten, das ist ja gerade der Grund, warum C++ entwickelt wurde.
-
Danke für eure Antworten.
-
Da es ja so viele verschiedene Meinungen gibt, möchte ich hier doch noch
einmal fragen. Was haltet ihr von folgenden Büchern:- C++ von A bis Z von Jürgen Wolf
- Einstieg in C++ von Arnold Willemer
- C++ für Spieleprogrammierer von Heiko Kalista
-
manni66 schrieb:
BasicMan01 schrieb:
bis auf conio.h und _getch, wo man lieber nen cin.get() verwenden sollte, ist doch alles C++
oder lieg ich jetzt falsch
Ja und nein
Das Programm benutzt nur den C-Anteil von C++. Gerade für eine Liste würden sich aber die objektorientierten Bestandteile anbieten, das ist ja gerade der Grund, warum C++ entwickelt wurde.
Um die objektorientierten Bestandteile nutzen zu können, muss man im Buche oder Tutorial auch erstmal dort ankommen. Gerade die Speicherverwaltung (new / delete) ist C++. Die IO-Operationen (cin / cout) sind C++ ... namespace = C++.
Nur weil man NOCH keine Klasse nutzt, wird ein Programm nicht zum C-Programm.
-
BasicMan01 schrieb:
Nur weil man NOCH keine Klasse nutzt, wird ein Programm nicht zum C-Programm.
Es gibt keinen Grund, NOCH keine Klassen zu nutzen! Das ist eben der falsche Ansatz, der scheinbar auch in dem Wolf Buch verfolgt wird: erst mal C lernen, und dann kommt das tolle C++ dazu.
-
manni66 schrieb:
BasicMan01 schrieb:
Nur weil man NOCH keine Klasse nutzt, wird ein Programm nicht zum C-Programm.
Es gibt keinen Grund, NOCH keine Klassen zu nutzen! Das ist eben der falsche Ansatz, der scheinbar auch in dem Wolf Buch verfolgt wird: erst mal C lernen, und dann kommt das tolle C++ dazu.
ich versteh aber net, was new, delete, cin und cout mit C zu tun hat.
-
BasicMan01 schrieb:
manni66 schrieb:
BasicMan01 schrieb:
Nur weil man NOCH keine Klasse nutzt, wird ein Programm nicht zum C-Programm.
Es gibt keinen Grund, NOCH keine Klassen zu nutzen! Das ist eben der falsche Ansatz, der scheinbar auch in dem Wolf Buch verfolgt wird: erst mal C lernen, und dann kommt das tolle C++ dazu.
ich versteh aber net, was new, delete, cin und cout mit C zu tun hat.
zunächst mal nichts, aber das ist gar nicht das Thema. Natürlich ist new/delete C++, aber in diesem von Honky vorgestellten Programm, als 'Anfängerübung' - zumal unter der Voraussetzung 'Klassen kommen später', hat new/delete nichts zu suchen.
Ich unterstelle mal, dass in meinem Umfeld, in dem ich arbeite, einigermaßen professionell C++ programmiert wird. Wir arbeiten an Programme in der Größenordnung einiger 100-tausend Zeilen Sourcecode. Diese Programme sind zum großen Teil sogenannte Anwenderprogramme, d.h. sie sind für eine bestimmte Anwendung geschrieben und nicht als Library, um von anderen Programmen benutzt zu werden - wie z.B. die Container des C++-Standards. Anfänger sollten sich zunächst immer auf Anwenderprogramme beschränken - alles andere ist weit aus schwieriger.
In diesem Programmen findet man delete praktisch gar nicht mehr und new nur im Kontext mit Smartpointern. Wobei die Anwendung von new sich auf zwei Bereiche beschränkt - Polymorphe Objekte und Objekte, die - aus welchen Gründen auch immer - nicht kopiert werden sollen.Bevor ein Anfänger mit polymorphen Objekten agiert, muss er erst mal Vererbung lernen und vor der Vererbung kommen die Klassen. Ähnliches gilt für die Smartpointer. Erst wenn man sich mit diesen Themen auseinander setzt, kommt man zu der Anforderung, Objekte auf den Heap zu legen. Und damit erst zu new und delete.
Eine kleine Anekdote dazu. Nichts ist perfekt und wir auch nicht; so hatten wir vor ca. einem halben Jahr doch tatsächlich einen Memoryleak in unserem Programm, der sich aber erst nach ca. 10 Stunden Laufzeit bemerkbar machte. Wir haben ziemlich lange suchen müssen .. schließlich fanden wir das Problem in einem 8 Jahre alten Modul, wo ein einsames new ca. 16 Byte allokierte. Das zugehörige delete war im Destruktor der Klasse implementiert, nur im Laufe der Jahre hatten sich die äußeren Umstände derart verändert, dass man mehrfach die Methode mit dem new aufrufen konnte, ohne das Objekt zu löschen und damit den Destruktor mit dem delete aufzurufen.
Der 'Spaß' hat die Firma sicher einige 1000EUR gekostet. Und was ich damit sagen will ist: new/delete ohne Smartpointer haben in einem üblichen C++-Anwendungsprogramm nichts zu suchen. Und dies sollte ein Anwender lernen, bevor er lernt (bzw. nicht lernt!) mit new und delete umzugehen. Vor new und delete müssen Klassen mit Konstruktor und Destruktor verstanden sein. Und gleichzeitig muss klar sein, wie man string und vector & Co einsetzt. Alles andere macht keine Sinn und ist unwirtschaftlich .. und es macht auf Dauer auch keinen Spaß mit Programmen zu arbeiten, die voll mit solchen Fehlern sind - beruflich und privat.
Ich will damit nicht sagen, dass ein Anfänger nicht mal eine einfache Liste codieren soll. Nur er sollte vorher wissen, wie man std::list benutzt; er sollte mit einer Klasse und der Idee der Kapselung umgehen können - das kommt alles vorher.
Gruß
Werner
-
Honky schrieb:
Da es ja so viele verschiedene Meinungen gibt, möchte ich hier doch noch
einmal fragen. Was haltet ihr von folgenden Büchern:- C++ von A bis Z von Jürgen Wolf
- Einstieg in C++ von Arnold Willemer
- C++ für Spieleprogrammierer von Heiko KalistaIch kenne hier im Forum niemanden, der einigermaßen C++ kann und das Buch von J.W. gut findet. Gut an dem Buch finde ich das Vorwort des Fachgutachters. Dort heißt es u.a.(ich zitiere aus dem 'Blick ins Buch' bei amazon.de):
Es ist .. notwendig, den objektorientierten Ansatz zu verstehen und die Möglichkeiten zu kenne, die C++ bietet. Fehlendes Wissen kann hier zu groben ärgerlichen Designfehlern und viel überflüssiger Arbeit führen
Allein aus dem Inhaltsverzeichnis kann man schließen, dass das Buch hier ein Problem hat.
Die beiden anderen Bücher sind mir nicht bekannt.
Gut finde ich das Buch von Andrew Koenig und Barbara E. Moo "Accelerated C++" - ist leider in Englisch; es gibt aber anscheinend eine deutsche Übersetzung.Gruß
Werner
-
Werner Salomon schrieb:
BasicMan01 schrieb:
manni66 schrieb:
BasicMan01 schrieb:
Nur weil man NOCH keine Klasse nutzt, wird ein Programm nicht zum C-Programm.
Es gibt keinen Grund, NOCH keine Klassen zu nutzen! Das ist eben der falsche Ansatz, der scheinbar auch in dem Wolf Buch verfolgt wird: erst mal C lernen, und dann kommt das tolle C++ dazu.
ich versteh aber net, was new, delete, cin und cout mit C zu tun hat.
zunächst mal nichts, aber das ist gar nicht das Thema.
Doch, genau das war ja der Grund, warum ich mich zu Wort gemeldet habe.
Mit dem Rest stimme ich dir natürlich überein.
Mir scheint aber, dass die meisten Bücher und Tutorials die dynamische Speicherverwaltung vor Klassen behandeln. Und das scheint dann wohl nicht nur beim Wolf so zu sein (kenne sein Buch ja nicht)