Welche Sprache lernen ?
-
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.
-
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.
-
Hallo,
also Du schreibst :
- Du baust ein Kiste, und notierst dir auf einem Zettel, wo du sie hingestellt hast.
--> int * Kiste = new int[2];- Du nimmst einen weiteren Zettel
--> int * TempKiste = new int[3];- und überträgst die Daten des ersten auf diesen.
--> TempKiste[0] = Kiste[0];
--> TempKiste[1] = Kiste[1];- Irgendwann später nimmst du den ersten Zettel, suchst die Kiste und machst sie kaputt.
--> delete[](Kiste); ???- Danach zerreißt du dann den ersten Zettel.
--> ???????????????????? Hab ich doch schon gemacht mit delete[](Kiste); oder nicht ?- Du hast zwar noch den zweiten Zettel, auf dem steht, wo die Kiste war, aber die Kiste ist trotzdem weg.
--> und das verstehe ich dann nicht ?
--> Wieso ist denn die Kiste kaput ?Nur weil du einen Zettel (Zeiger) kopierst, hast du noch lange keine zweite Kiste.
Kannst Du das ganze bitte nochmal ZUSAMMENHÄNGEND, so wie es richtig sein muss , mit KOMMENTAREN posten ?
Matthias
-
- Du baust ein Kiste, und notierst dir auf einem Zettel, wo du sie hingestellt hast.
int *zettel = new int;
cout << zettel;- Du nimmst einen weiteren Zettel und überträgst die Daten des ersten auf diesen.
int *zettel2 = zettel;
cout << zettel2;- Irgendwann später nimmst du den ersten Zettel, suchst die Kiste und machst sie kaputt.
delete zettel;
zettel = NULL; //
cout << zettel;- Danach zerreißt du dann den ersten Zettel.
out of scope- Du hast zwar noch den zweiten Zettel, auf dem steht, wo die Kiste war, aber die Kiste ist trotzdem weg.
cout << zettel2; // aha?!
-
Pointer mal anders erklärt:
http://www.cs.stanford.edu/cslibrary/PointerFunCpp.avi (14 MB version)
http://www.cs.stanford.edu/cslibrary/PointerFunCppBig.avi (34 MB version)
-
Nimm nen Apfel, mach zwei Schilder mit nem Pfeil drauf die auf den Apfel zeigen.
Dann sagst Du delete Schild 1, nimmst das Schild weg und isst den Apfeln. Jetzt versuchst Du den Apfel zu Essen auf den Schild zwei zeigt.
-
Artchi schrieb:
- Du baust ein Kiste, und notierst dir auf einem Zettel, wo du sie hingestellt hast.
int *zettel = new int;
cout << zettel;- Du nimmst einen weiteren Zettel und überträgst die Daten des ersten auf diesen.
int *zettel2 = zettel;
cout << zettel2;- Irgendwann später nimmst du den ersten Zettel, suchst die Kiste und machst sie kaputt.
delete zettel;
zettel = NULL; //
cout << zettel;- Danach zerreißt du dann den ersten Zettel.
out of scope- Du hast zwar noch den zweiten Zettel, auf dem steht, wo die Kiste war, aber die Kiste ist trotzdem weg.
cout << zettel2; // aha?!Hallo,
ja aber so mach ich das doch gar nicht !
Das was Du hier erklärt hast habe ich verstanden .Aber int *zettel2 = zettel; ?????
Kannst Du mal Bitte bei dem Kisten Beispiel bleiben?
Ansonsten bringen mich ja die vielen vershciedenen Beispiele noch zusätzlich durcheineander....danke !Also nachmal das was ich mache(n soll) :
Im groben geht es ja darum eine Kiste ( intArray ) zu vergrößern.
Also ich hab nen intArray mit 2 Werten und möchte diesen um einen Wert erweitern so das er 3 Werte aufnehmen kann.
Bsp: Kiste in die 2 IntWerte passen soll so verändert werden das in Kiste 3 intWerte passen.Ich hab ne Kiste in die passen 2 int Werte
--> int * kiste = new int[2]; // Also ne Kiste mit 2 intWertenNun eine TEMPORÄRE Kiste erstellen
--> int TempKiste = new int[3]; // TempKiste mit 3 intWertenWerte aus Kiste in TempKiste kopieren
--> TempKiste[0] = Kiste[0]; ... [1] = [1];Neuen Wert in TempKiste aufnehmen
--> TempKiste[2] = 3; // Dritter intWert ist in TempKiste.Ok, bis hierher alles klar.
Ich habe zwei Zeiger ( kiste und TempKiste ).
Zeiger sollen ja unter C++ immer wieder gelöscht werden und das ist ja der knackpunkt. Die TempKiste soll ja nur ein Temporärer Zeiger sein, also müsste der doch wieder gelöscht werden können nach der Methode oder?Also ich habe immer noch 2 Kiste, eine Kiste in die 2 intWerte passen und eine TempKiste in der 3 intWerte drin sind, die beiden aus der Kiste und der 3.intWert der dazugekommen ist.
Soweit so gut.Jetzt kann ich doch die Kiste löschen, denn die kann ja nur mit 2 intwerten und deswegen brauche ich die nicht mehr. Ich habe ja alle Werte bereits in der TempKiste zwischengespeichert.
Also
--> delete[](kiste);Jetzt soll aber meine Kiste ( zeiger ) nicht TempKiste heisßen sondern wie gehabt Kiste, damit meine Arbeiter nicht durcheinander kommen.
Da es ja keine Kiste mehr gibt mach ich eine neue und die auch wieder mit 3 Werten ( was ja das Ziel des ganzen ist )--> int * kiste = new int[3]; // neue Kiste die nun auch mit 3 intWerten kann
Ok, nun kopieren wir doch alle Werte aus der Temporären Kiste ( TempKiste ) wieder in die niegelnagelneue Kiste:
--> kiste[0] = TempKiste[0];
--> kiste[1] = TempKiste[1];
--> kiste[2] = TempKiste[2];So, mein Zeiger ( kiste ) zeigt doch nun auf kist und nicht auf TempKiste oder ?
Warum kannich dann die blöde TempKiste nicht
--> delete[](TempKiste);
löschen ?
Das verstehe ich nicht ?So, könntet Ihr nun bitte bei DIESEM Beispiel bleiben ?
Danke
Matthiasps.: Danke für die niedlichen Videos !
-
Hast Du dir das Video mal angesehen ?
Wo ist da jetzt noch das Problem ?
-
Zeiger sollen unter C++ nicht immer wieder gelöscht werden. Wer hat dir denn den Floh ins Ohr gesetzt? Ich sage und kenne das so: Man löscht seine Objekte DANN, wenn man sie nicht mehr benötigt. Hat doch schon eine ganz andere Aussage, oder?
Weiterhin scheinst du dir meine Richtigstellung mit den Kisten nicht angeschaut zu haben. Warum verharrst du so doll auf DEIN Beispiel? Wir versuchen dir die Pointer einfach anders zu erklären. Wenn du die einfachen Beispiele nicht verstehst, nützt dir DEIN Beispiel nicht viel weiter. Das Pointerfun-Video soll man auch nicht niedlich finden, man soll es sich ansehen, zu hören und versuchen zu verstehen! Notfalls mehrmals das Video anschauen. Das Video zeigt animatorisch, was wir dir versuchen hier zu erklären. Meine Kisten-Anwort auf Rüdigers Beispiel ist ähnlich dem Video.
-
Artchi schrieb:
1.:::
Zeiger sollen unter C++ nicht immer wieder gelöscht werden. Wer hat dir denn den Floh ins Ohr gesetzt? Ich sage und kenne das so: Man löscht seine Objekte DANN, wenn man sie nicht mehr benötigt. Hat doch schon eine ganz andere Aussage, oder?2.:::
Weiterhin scheinst du dir meine Richtigstellung mit den Kisten nicht angeschaut zu haben. Warum verharrst du so doll auf DEIN Beispiel?3.:::
Wir versuchen dir die Pointer einfach anders zu erklären. Wenn du die einfachen Beispiele nicht verstehst, nützt dir DEIN Beispiel nicht viel weiter.4.:::
Das Pointerfun-Video soll man auch nicht niedlich finden, man soll es sich ansehen, zu hören und versuchen zu verstehen! Notfalls mehrmals das Video anschauen. Das Video zeigt animatorisch, was wir dir versuchen hier zu erklären. Meine Kisten-Anwort auf Rüdigers Beispiel ist ähnlich dem Video.Zu 1.:::
Genau !! Zeiger die man nicht mehr braucht soll man löschen steht in meinem Buch hier !
Wenn ich "immer wieder" geschrieben habe tut es mir leid. Ich habe das aber so gemeint das man Zeiger die man nicht mehr benötigt wieder löschen soll, also das es in der Hand des programmierers liegt...sorry !!!Zu 2.:::
Weil ich das Zeigern schon nicht verstehe und wenn ich bei jeder Antwort von Euch erst mal ein neues Beispiel verstehen soll, dann bringt mich genau das nicht weiter.
Deswegen bitte bei meinem Beispiel bleiben !Zu 3.:::
Gut und schön, aber deswegen ist int * zettel = new int;
nicht das gleiche wie int * zettel = new int[2];Zu 4.:::
Das Video ist sehr hilfreich und eben auch niedlich,
Ich habs mir angeschaut und es dreht sich gar nicht um mein problem !int * x;
int * y;x = new int;
*x = 42;*y = 13; // Error, logisch weil noch nicht erzeugt, zeigt als ins nirvana
y = x;usw......ist mir klar.
Hat aber wie gesagt auch absolut nix mit dem zu tun was hier mein Problem ist !
Trotzdem war es Hilfreich !
Und eben auch niedlich...sorryNun hab ich aber die Lösung gefunden:
Könt es ja mal ausprobieren :
int main() { int * Kiste = new int[2]; // 2 Werte in Kiste 1 // Werte zuweisen Kiste[0] = 0; Kiste[1] = 1; // TestAusgabe cout << "Ausgabe der Originalkiste mit den 2 intWerten: " << endl; cout << "Kiste 0: " << Kiste[0] << endl; cout << "Kiste 1: " << Kiste[1] << endl << 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 << "Ausgabe der TempKiste die 3 intWerte aufnehmen kann:" << endl; 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 << " 3.Wert der TempKiste noch undefiniert !:" << endl; cout << "TempKiste 2: " << TempKiste[2] << endl << endl; // Den letzten Wert zuweisen TempKiste[2] = 3; // TestAusgabe cout << " dem 3.intWert wurde die Zahl 3 zugewiesen:" << endl; cout << "TempKiste 2: " << TempKiste[2] << endl << endl; // Alte Kiste löschen delete[](Kiste); // und neu ( mit 3 werten ) erstellen: int * kiste = new int[3]; // Hier war mein Fehler !!! // der neuen größeren Kiste die TempWerte zuweisen: kiste[0] = TempKiste[0]; kiste[1] = TempKiste[1]; kiste[2] = TempKiste[2]; // Da die kiste jetzt die gleichen Werte wie die TempKiste // enthält kann die TempKiste weg !!!! // ******************************************************* // Zeiger die man nicht mehr benötigt soll man löschen !!! // ******************************************************* delete[](TempKiste); // TestAusgabe cout << "Woila...unsere neue ( alte ) kiste namens kiste kann jetzt mit 3 intWerten :" << endl; cout << "Kiste 0: " << Kiste[0] << endl; cout << "Kiste 1: " << Kiste[1] << endl; cout << "Kiste 2: " << Kiste[2] << endl << endl; // TestAusgabe // Nun ist auch logisch das diese Werte hier ndefiniert sind. cout << "TempKiste ist logisch undefiniert, zeigt also auf nix:" << endl; cout << "TempKiste 0: " << TempKiste[0] << endl; cout << "TempKiste 1: " << TempKiste[1] << endl; cout << "TempKiste 2: " << TempKiste[2] << endl; system("Pause"); }Ich habs mühselig kommentiert, was auch noch ein Grund ist warum ich es schön fände wenn Ihr mal meine Beispielcodes verändert zurückposten würdet.
Matthias
-
Zu 4.:::
Das Video ist sehr hilfreich und eben auch niedlich,
Ich habs mir angeschaut und es dreht sich gar nicht um mein problem !Doch genau das ist Dein Problem (nebst Deiner Sturheit).
Was Du jetzt machst ist doppelte Kopierarbeit. Dein Quellcode zeigt, das Du von dem Film das entscheidende nicht verstanden hast. Ich wüsste nicht wie sonst das hier zustande kommt:
int * kiste = new int[3]; // Hier war mein Fehler !!! // der neuen größeren Kiste die TempWerte zuweisen: kiste[0] = TempKiste[0]; kiste[1] = TempKiste[1]; kiste[2] = TempKiste[2];Ein einfaches kiste = TempKiste OHNE löschen der TempKiste hätte es vollst auf getan. Du erzeugst lieber noch eine Kiste und packst alles noch mal um. Und das nur weil Du unbedingt die Kiste zerstören willst auf die TempKiste zeigt und nicht diese Kiste einfach als kiste zu verwenden.
