Welche Sprache lernen ?



  • 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 gibt

    for(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. Wert
    

    Somit ist

    feld = new int[_g];
    feld[_g-1] = wert; // letzen Wert setzen
    

    also richtig gewesen.



  • STF-DIR schrieb:

    eine Kiste in der 2 int werte liegen
    int *Kiste = new int[1];

    eine größere Kiste haben in die 3 Werte passen
    int *TempKiste = new int[2];

    Du musst auch 2 und 3 in den eckigen Klammern übergeben. Das gibt die Größe des Arrays an! Du bist wahrscheinlich ein bisschen irritiert, weil man auf das erste Element eines Array mit der 0 zugreift. Beim Anlegen ist das aber nicht so 😉



  • Hallo,

    na wenn :

    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.

    das so ist, dann ist mir aber schon wieder nicht klar warum ich nicht die blöde TempKiste löschen kann ?

    Du meinst doch das nach der Anweisung

    Kiste = TempKiste;

    Kiste auf das zeigt auf das auch TempKiste zeigt ja ????

    Falls ja, dann hab ich's leider immer noch nicht begriffen.
    Zu was brauch ich denn in diesem Fall die TempKiste?
    Es soll doch jeder der einen IntWert braucht wieder ( wie vor der erhöhung der Werte ) bei Kiste nachschauen wo die Werte sind.

    Matthias .. ( Sorry )



  • Ich habs jetzt nochmal in Code gefasst :

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	int * Kiste = new int[2]; // 2 Werte in Kiste 1
    	// Werte zuweisen
    	Kiste[0] = 0;
    	Kiste[1] = 1;
    
    	// TestAusgabe
    	cout << "Kiste 0: " << Kiste[0] << endl;
    	cout << "Kiste 1: " << Kiste[1] << endl;
    
    	// TempKiste ( 3 Werte ) erstellen
    	int * TempKiste = new int[3];
    
    	// Tempkiste die 2 Werte der Kiste zuweisen
    	TempKiste[0] = Kiste[0];
    	TempKiste[1] = Kiste[1];
    
    	// TestAusgabe
    	cout << "TempKiste 0: " << TempKiste[0] << endl;
    	cout << "TempKiste 1: " << TempKiste[1] << endl;
    
    	// Hier wird irgendwas angezeigt ( TempKiste[2] )
    	// Mir klar, da der Wert noch nicht zugewiesen ist
    	cout << "TempKiste 2: "	<< TempKiste[2] << endl;  
    
    	// Den letzten Wert zuweisen
    	TempKiste[2] = 2;
    
    	// TestAusgabe
    	cout << "TempKiste 2: " << TempKiste[2] << endl;
    
    	// Soweit ist alles klar !!!!
    	// *********************************
    	// Ab hier wirds ein bischen unklar
    
    	delete[](Kiste);
    	Kiste = TempKiste;
    
    	// Genau hier verstehe ich es nicht ??
    	// Warum kann ich die blöde TempKiste niciht löschen ?
    	// Kiste = TempKiste ???? delete[](TempKiste);
    	delete[](TempKiste);
    
    	// TestAusgabe
    	cout << "Kiste 0: " << Kiste[0] << endl;
    	cout << "Kiste 1: " << Kiste[1] << endl;
    	cout << "Kiste 2: " << Kiste[2] << endl;
    
    	// TestAusgabe
    	cout << "TempKiste 0: " << TempKiste[0] << endl;
    	cout << "TempKiste 1: " << TempKiste[1] << endl;
    	cout << "TempKiste 2: "	<< TempKiste[2] << endl;
    
    	system("Pause");
    }
    

    Vielleicht könnt Ihr hieran mein Verständnis Problem erkennen und auch daran beheben ( erklären ) bitte

    Danke
    Matthias



  • Ps.:

    ist mir gerade beim herumtesten aufgefallen ...

    int * a = new int[0];
    
    	a[0] = 1;
    	a[1] = 2;
    	a[2] = 3;
    
    	cout << "a_0:" << "-" << a[0] << endl;
    	cout << "a_1:" << "-" << a[1] << endl;
    	cout << "a_2:" << "-" << a[2] << endl;
    

    Warum kann ich das denn OHNE FEHLER kompilieren ???

    Matthias
    Sehr verwirrend oder ?



  • Weil es gueltiger C++-Code ist. Und nein. Es ist nicht verwirrend.



  • Apollon schrieb:

    Weil es gueltiger C++-Code ist. Und nein. Es ist nicht verwirrend.

    schön und WARUM ist es gültiger C++ code ??
    Was ist mit der forigen Frage wo ich wieder nen Meter code extra geschrieben habe ? War das wieder umsonst oder bekomme ich da auch ne Antwort ?

    Das war ja wieder ne Antwort ... danke

    MAtthias



  • STF-DIR schrieb:

    Vielleicht könnt Ihr hieran mein Verständnis Problem erkennen und auch daran beheben ( erklären ) bitte

    - Du baust ein Kiste, und notierst dir auf einem Zettel, wo du sie hingestellt hast.
    - Du nimmst einen weiteren Zettel und überträgst die Daten des ersten auf diesen.
    - Irgendwann später nimmst du den ersten Zettel, suchst die Kiste und machst sie kaputt.
    - Danach zerreißt du dann den ersten Zettel.
    - Du hast zwar noch den zweiten Zettel, auf dem steht, wo die Kiste war, aber die Kiste ist trotzdem weg.

    Nur weil du einen Zettel (Zeiger) kopierst, hast du noch lange keine zweite Kiste.


Anmelden zum Antworten