Welche Sprache lernen ?
-
Ja, aber lies doch mal die Kommentare die da stehen
bzw. schau mal in Deinem Buch nach was beim Zuweisen
der Zeiger passiert.Hier mal die Kurzversion:
temp = feld; // Werte aus altem intFeld dem TempIntFeld zuweisen delete[](feld); // Altes Feld löschen feld = temp; // Feld wird Temp zugewiesen delete[](temp); // Hier ist derDu löschst den gleichen Zeiger zweimal.
In dem kurzen Codestück hast Du
2 x Memoryleaks
1 x Speicherzugriffsfehler
1 x Speicher doppelt löscheneventuell komme noch 1 logischer Fehler hinzu:
_g+=1;
int *temp = new int[_g+1];
-
Hallo,
ja, ich bin ja am lernen .. entschuldige das ich es noch nicht geschnallt habe
Hier ist der orginal code aus dem Buch :
*.h
#pragma once class DynIntFeld { int *feld; int groesse; int kapazitaet; public: DynIntFeld(): feld(new int[2]), groesse(0), kapazitaet(2) {} DynIntFeld(int g): groesse(g), kapazitaet(g) { feld = new int[groesse]; } ~DynIntFeld() { delete[](feld); } void setWert(int pos, int wert) { feld[pos]=wert; } int getWert(int pos) const { return(feld[pos]); } int size() const { return(groesse); } int capacity() const { return(kapazitaet); } void add(int wert) { if(groesse>=kapazitaet) { int* nf=new int[kapazitaet*2]; for(int i=0; i<groesse; ++i) nf[i]=feld[i]; delete[](feld); feld=nf; kapazitaet*=2; } feld[groesse++]=wert; } };und
*.cpp
#include <iostream> #include <vector> #include "DynIntFeld.h" using namespace std; int main() { cout << "Wie viele Werte:"; int x; cin >> x; DynIntFeld f; for(int i=0; i<x; ++i) { cout << "Wert " << i+1 << ":"; int w; cin >> w; f.add(w); } for(int i=0; i<f.size(); ++i) cout << "Wert " << i+1 << ": " << f.getWert(i) << endl; cout << "Feldkapazitaet: " << f.capacity() << endl; system("pause"); }Ich weiß auch nicht wirklich was er da mit der kapazität macht ??
Was ich nicht verstehe ist das laut deiner Aussage ( glaube ich ) das hier nicht richtig ist ?feld=nf;
Ich denke das geht nicht ?
Sorry aber ich habs noch nicht verstanden.
Bei mir is es jetzt so :void CIntFeld::Add(int wert) { _g++; std::cout << "_g: " << _g << std::endl; int *temp = new int[_g]; for(int x=0; x<=_g; x++) temp[x] = feld[x]; feld[_g-1] = wert; //delete[](temp); }Das delete[](temp); verursacht aber einen Fehler und ich weiß nicht warum ?
Matthias
-
Erkläre mal bei jeder Zeile Deine Gedanken warum Du es so gemacht hast und erläutere was Deiner Meinung nach passieren sollte.
-
Habs gefunden ...sorry !!!
void CIntFeld::Add(int wert) { _g++; std::cout << "_g: " << _g << std::endl; int *temp = new int[_g]; for(int x=0; x<_g; x++) // x<_g nicht x<=_g temp[x] = feld[x]; feld[_g-1] = wert; delete[](temp); }Eben ein Denkfehler.
Trotzdem steht die frage was der da mit
feld=nf;
macht ?
Matthias
-
Eine Zuweisung ?
Ich frag mich eher was Du mit temp machst, wenn Du es eh weg wirfst
-
Hallo,
ich glaube ich habs jetzt kapiert.
Hab mal Kommentare geschrieben.
Könntest Du mich nochmal berichtiogen falls ich da was falsch verstanden habe ( immernoch )main.cpp ( so wird das Objekt erzeugt, sind also 2 Elemente .. nur zur info )
CIntFeld *f = new CIntFeld(2); f->setWert(0,0); f->setWert(1,1);void CIntFeld::Add(int wert) { // Größe des Feldes um 1 erhöhen weil ein wert dazu kommt _g++; // Einen neuen Zeiger auf einen IntArray erstellen // Größe = _g ( also 3 nach dem ersten Aufruf von Add() int *temp = new int[_g]; // Jedem Wert von Temp[x] wird der gleiche wert wie Feld zugewiesen // Schleife geht bis 2 !! for(int x=0; x<_g; x++) temp[x] = feld[x]; // Hier wird der originale Zeiger auf Feld verworfen delete[](feld); // ..und hier haben wir wieder einen Zeiger namens Feld der // hier die Adresse von temp zugewiesen bekommt oder ? feld = temp; // Hier wird nur noch dem letzten Element der neue // Wert zugewiesen feld[_g-1] = wert; }Ich hoffe das stimmt jetzt so ?
Matthias
-
Ja, Du schreibst aber den neuen Wert in das vorletzte Feld des Arrays.
Unterstriche als Anfang einer Variable solltest Du vermeiden, wirf häufig von Implmentierungen des Compilers verwendet (lasst die Goldwaage stecken ;o) .
-
Hallo,
ok, die mit Unterstrichen sind bei mir die als private deklarierten. War so ein Einfall

Trotzdem ( sorry sorry ) habe ich etwas nioch nicht ganz kapiert.
Warum kann ich denn am ende der procedure den temp Zeiger nicht löschen ?
Ich habe doch mit
feld = temp;
die Adresse von temp an feld zugewiesen oder versteh ich das falsch ?
feld und temp sind doch Zeiger und Zeiger speichern Adressen.
Dann müsste doch eigentlich temp nach der Methode unnütz sein oder ?
Warum kann ich den nicht löschen ?delete[](temp);
geht zwar ohne Fehler aber dann sind die Werte von feld leer ??
Also in der main.cpp gibtfor(int x=0; x<=f->getSize()-1; x++) { cout << "nachher " << x << " : " << f->getWert(x) << endl; }blödsinnige werte aus.
Sorry aber ich muss das genau verstehen sonst brauch ich nicht weiterlesen. Das bringt nix.
Danke für Dein Verständnis !!
Matthias
-
Was heißt weiterlesen ? Mal vorne Anfangen meinst.
temp benötigst Du weil für das Vergrößern eines Arrays neuer speicher angelegt sein muss.
temp wird in Deinem geposteten Code nicht gelöscht.
Ohne aktuellen Code kann man Dir nix sagen.
-
Hallo,
nein, ich meine schon WEITERLESEN, denn das ist ja das erste Kapitel wo es sich um sowas dreht.
Sorry, aber wenn Du auch mal lesen würdest :.
.
Dann müsste doch eigentlich temp nach der Methode unnütz sein oder ?
Warum kann ich den nicht löschen ?delete[](temp);
geht zwar ohne Fehler aber dann sind die Werte von feld leer ??
Also in der main.cpp gibt
.
.Dann würden es nicht immer soooo viele Postings werden.
Meckern kann jeder, erklären leider nicht
Matthias
-
temp wird in Deinem geposteten Code nicht gelöscht.
Ohne aktuellen Code kann man Dir nix sagen.
Wenn Du lesen würdest, müsste man nich so viel mosern ;o)
-
So, hier nochmal der code wie er nicht funktioniert :
void CIntFeld::Add(int wert) { // Größe des Feldes um 1 erhöhen weil ein wert dazu kommt _g++; // Einen neuen Zeiger auf einen IntArray erstellen // Größe = _g ( also 3 nach dem ersten Aufruf von Add() int *temp = new int[_g]; // Jedem Wert von Temp[x] wird der gleiche wert wie Feld zugewiesen // Schleife geht bis 2 !! for(int x=0; x<_g; x++) temp[x] = feld[x]; // Hier wird der originale Zeiger auf Feld verworfen delete[](feld); // ..und hier haben wir wieder einen Zeiger namens Feld der // hier die Adresse von temp zugewiesen bekommt oder ? feld = temp; // Hier wird nur noch dem letzten Element der neue // Wert zugewiesen feld[_g-1] = wert; // HIER IST DAS WAS ICH NICHT GANZ VERSTEHE BEGIN !!! delete[](temp); // HIER IST DAS WAS ICH NICHT VERSTEHE ENDE !!! }
-
Auch wenn es sich jetzt hart anhört:
Denk doch mal nach

Hier mal die Kurzform von dem was Du machst:
void CIntFeld::Add(int wert) { int *temp = new int[_g]; feld = temp; delete[] temp ; }Wir besorgen und speicher, kopieren die Adresse nach feld und löschen dann den angeforderten Speicher über temp.
-
Knuddlbaer schrieb:
Auch wenn es sich jetzt hart anhört:
Denk doch mal nach

Hier mal die Kurzform von dem was Du machst:
void CIntFeld::Add(int wert) { int *temp = new int[_g]; feld = temp; delete[] temp ; }Wir besorgen und speicher, kopieren die Adresse nach feld und löschen dann den angeforderten Speicher über temp.
Das hört sich nicht hart an, hilft mir nur nicht weiter.
Der Satz von Dir ist völlig unverständlich. Was soll ich denn damit anfangen.
Kannst Du es nicht einfach mal ERKLÄREN oder willst Du nicht ?
Wenn ich es durch überlegen und grübeln selber wissen würde, dann würd ich doch nicht frage ! Versthst du das nicht ?
Wenn du das nicht versthst, das ich hier Frage um eine Antwort bzw. ERKLÄRUNG zu erhalten, dann antworte bitte nicht mehr auf meine Fragen da so die Postings immer ewig lang werden undander, die vielleicht in der Lage sind mir wirklich zu helfen hier nicht mehr reinschauen.Matthias
-
Na, Du willst einfach keine Energie investieren wenn es um das Programmieren geht. Du willst einfach nicht mal drüber nachdenken...
Aber gut.
Du legst ein neues Feld an, kopierst die Werte rein und löschst es am Ende wieder. Jeder Zugriff auf diesen Speicher ist völlig undefiniert, da darf passieren was auch immer passieren will.
Nimm einfach mal ein Blatt Papier und spiele mal Computer, führe Deinen Quellcode aus. Male dabei ein Kasten mit dem Inhalt, fülle ihn und schau mal was passiert wenn Du den Kasten dann wegwirfst.
Ich kann doch von hier aus nicht beurteilen was Du da im Detail nicht verstehst bzw. welche Lücken Du hast.
void CIntFeld::Add(int wert) { int *temp = new int[_g]; feld = temp; delete[] temp ; }Zeigt deutlich, das Du den Speicher den Du besorgst einfach wegwirfst. Das Du jetzt so viele Lücken hast, das Dir das nichts sagt, kann hier keiner wissen.
Ich könnte jetzt raten das Du nicht verstehst, was die Zuweisung von Zeigern bedeutet, aber in dem Du Dich hinstellst und heulst macht es nicht verständlicher was genau Du nicht verstehst.
-
Hallo,
genau das scheint es aber zu sein was ich nicht so ganz verstehe.
Das hab ich aber schon geschrieben ! ( eine Seite zuvor )Ich weiß auch nicht wirklich was er da mit der kapazität macht ??
Was ich nicht verstehe ist das laut deiner Aussage ( glaube ich ) das hier nicht richtig ist ?feld=nf;
Ich denke das geht nicht ?
Sorry aber ich habs noch nicht verstanden.
Bei mir is es jetzt so :void CIntFeld::Add(int wert) { int *temp = new int[_g]; feld = temp; delete[] temp ; }--> int *feld = new int[2];
Also ich habe einen Kasten_1 mit 2 beschrifteten Kugeln drin, das soll jetzt mal feld sein. ok?--> int *temp = new int[3];
Nun habe ich einen Temporären Kasten_2 mit 3 unbeschrifteten Kugeln drin ok ?--> temp[0] = feld[0];
--> temp[1] = feld[1];
( in ner schleife ) Jetzt sind aber die 2 Kugeln in Kasten_1 ( temp ) also auch beschriftet ( mit werten gefüllt ) Ok ????? ist das jetzt das gleiche wie temp = feld; ????
Wo hab ich denn da jetzt den Denkfehler ?
Ich kapier das nich , sorry
Grundlagen ---> Das sind doch die Grundlagen, ich hab doch ganz vorne angefangen, bzw bin ich ja noch ganz am Anfang des Buches.
Der geht aber gerade auf das nicht weiter ein.
Matthias
-
Ok, wir kommen der Sache näher

Mit = weist Du die Elemente zu.
Mit kiste[Platz] = kiste2[platz] weist Du Objekte vom Typ Kugel zu. (In Deinem speziellen Fall sind die Kugeln int )
Die Kisten stehen jetzt irgendwo im Raum (Arbeitsspeicher des Computers).
Mit feld können wir sagen WO die Kiste nun im Raum steht. (Schau mal ins Buch, meist sind da zum Thema Zeiger noch nette Grafiken enthalten).
Wenn wir nun in Feld schauen, steht da z.B. Die Kiste steht hinten Links.
Nun erstellst Du Kiste zwei und weisst sie dem Zeiger temp zu. temp weiß nun, das die Kiste hinten rechts steht.
Nun sagst Du jemanden, das er eine Kiste weg werfen soll. Welche er weg werfen soll, steht in feld. Er schaut also in Feld rein und weiß das er die Linke Kiste wegwerfen soll.
Jetzt haben wir ja alle alten Werte in die rechte Kiste kopiert und packen den neuen Wert noch rein.
Und da alle, die diese Werte verwenden, gesagt bekommen: "Aus welcher Kiste ihr nun die Kugeln nehmt, erfahrt ihr über Feld" , greifen nun alle auf die rechte Kiste zu.
Nun sagst Du aber einem Arbeiter, wirf mal eine Kiste weg. Welche steht in temp.
Er schaut also in temp rein und entsorgt nun die rechte Kiste.
Nun haben wir ja aber in feld definiert, das die rechte Kiste für aktuelle Werte verwendet werden soll. Aber die hat unser Mitarbeiter weggeworfen.
Mit feld = temp sagst Du also nur, worauf die Variable *zeigen* soll.
Mit feld = temp zeigen die Zeiger auf exakt das gleiche , und wenn Du sagst:
Wirf das weg, auf das temp zeigt ist es exakt das gleiche als wenn Du an dieser Stelle sagen würdest: Wirf das weg auf das Feld zeigt.
-
Nein, feld = temp ist NICHT das gleiche wie die Schleife.
Der Operator= weißt einfach den Wert zu bzw. macht das, was der Typ möchte was bei einer Zuweisung gemacht werden soll.
Bei einem Zeiger wird einfach nur der Finger, der auf einen Ort zeigt auf die gleiche Stelle geschoben wie bei dem anderen Zeiger.
Bei einem int wird auch einfach nur der Wert den ein int hat kopiert.
Ein std::vector dagegen kopiert bei einem = alle Elemente um die er besitzt. Ein ZEIGER auf einen Vektor leistet dies dann natürlich nicht, da hier wieder nur der "Finger" bewegt wird und der auf einen neuen Vektor zeigen würde.
Erklärungen auf dieser Ebene sind aber sehr mühsig und sprengen den Rahmen eines Forums. (Dafür sind Tutorials oder die Bücher da. Die stortzen dann auch nich so vor Rechtschreibfehlern :D)
-
Hallo,
ich glaub ich verstehe das jetzt so langsam.
Ja sorry, hab mich sicher ( bei der schilderung des Problems ) falsch ausgedrückt. C++ ist aber auch kompliziert...s schon die ganzen Dateien machen einen am Anfang ganz schön wirr.
Naja, also ich versuch es nochmal mit eigenen Worten zu erklären.
Sollte was nicht stimmen kannst Du ja dann vielleicht noch meine Worte ( Veranschaulichungen ) benutzen um meine Denkfehler aufzudecken, das wäre echt cool !Also ich habe eine Kiste_1 in der 2 int werte liegen. Das wäre dann
int *Kiste = new int[1];
Jetzt weiß jeder der einen Int Wert braucht das die in der Kiste sind.
Nun möchte ich eine größere Kiste haben in die 3 Werte passen:
int *TempKiste = new int[2];
So, jetzt weiß jeder das es ne Temporäre Kiste gibt in die 3 Werte passen.
Nützt aber noch keinem was, also mit der schleife die Werte der Kiste in die TempKiste kopieren:
TempKiste[0] = Kiste[0];
TempKiste[1] = Kiste[1];
und mit
TempKiste[3] = NeuerWert;
Hat die Temporäre Kiste nun 3 Int Werte.
Jeder der jetzt den 3. IntWert braucht kann den über TempKiste finden oder ?
Es soll aber jeder über Kiste auf den 3.IntWert kommen.
Also dachte ich mir
Kiste = TempKiste;
Somit dachte ich das jetzt die TempKiste überflüssig ist.
Ist aber glaube ich nicht so, wenn ich es richtig verstanden habe oder ?
Denn Kiste hat ja nun die Adresse von TempKiste gespeichert ( Zeiger speichern Adressen ).
Wenn ich also jetzt die TempKiste ( Adresse ) lösche kommt einer daher und schaut unter Kiste nach. Die verweist auf TempKiste...???
Die gibts aber nicht mehr ... also gibts nen Fehler.Stimmt das jetzt ( hoffentlich ) so ?
Matthias
-
Ja, wir kommen der Sache sehr nahe.
Kiste zeigt nicht auf tempkiste sondern Kiste zeigt auf das, auf das auch Tempkiste zeigt. Die Folgen sind dann aber die gleichen in Deinem Falle.
Beim Inidizieren Deiner Werte berücksichtige, das die Indizierung bei 0 beginnt.
feld[_g-1] = wert;War also richtig, ich hab beim Compilerspielen falsche Werte generiert =o)
Um ein Feld zu erzeugen, das 3 Elemente aufnimmt musst Du schreiben:
int * i = new int[3];Zuweisungen:
i[0] // 1. Wert i[1] // 2. Wert i[2] // 3. WertSomit ist
feld = new int[_g]; feld[_g-1] = wert; // letzen Wert setzenalso richtig gewesen.