Frage zu Zeigern
-
Hier ist erstmal der Code:
#include <iostream> using namespace std; class Mammal { public: virtual void Speak() const {cout << "Tier spricht\n";} private: int itsAge; }; class Dog : public Mammal { public: void Speak() const {cout << "Hund bellt\n";} }; class Cat : public Mammal { public: void Speak() const {cout << "Katze miaut\n";} }; class Pig : public Mammal { public: void Speak() const {cout << "Schwein oinkt\n";} }; class Duck : public Mammal { public: void Speak() const {cout << "Ente quackt\n";} }; int main() { Mammal *array[4]; Mammal *temp; for (int i=0; i<4; i++) { int save; cout << "1 Hund 2 Katze 3 Schwein 4 Ente\n"; cin >> save; switch(save) { case 1: temp=new Dog; break; case 2: temp=new Cat; break; case 3: temp=new Pig; break; case 4: temp=new Duck; break; } array[i]=temp; } return 0; }1.
In Zeile 61 steht "array[i]=temp;", also es funktioniert auch blendend, doch irgendwie komm ich bei Zeigern immer durcheinander und frage mich jetzt auch schon wieder warum das eigentlich funktioniert.
"array" ist doch ein Zeiger, und temp ist doch ein Zeiger, richtig?
Und nun will ich dem einem Manmal Zeiger (array) was übergebn. Was übergeb ich hier den eigentlich? Übergeb ich hier den Inhalt von "temp" oder übergeb ich die Adresse von "temp"? Eigentlich übergebe ich doch die Adresse, weil "temp" ohne "*" --> Adress oder?
So aber ich hab mal früehr gelernt das die Klammern "[ ]" den jeweiligen Zeiger dereferenzieren, also übergebe ich jeztt dem dereferenzierten Zeiger array[i] eine Adresse. Mh aber das kann doch nicht gehen oder? Aber es geht.
Also irgendwie bin ich wieder verwirrt, kanns mir jemand erklären?2.
Müsste ich eigentlich nicht nach jedem neuen Schleifen durchlauf "delete temp" machen? Weil sonst entstehen doch Speicherlücken oder? Aber das ist halt ein Buchbeispiel und ich vertrau dem mal? Wenn man nicht deleten muss dann erklärt mir doch bitte warum, meiner Meinung nach muss man deleten.Dankeschön schon mal im Voraus.
-
Stromberg schrieb:
"array" ist doch ein Zeiger, und temp ist doch ein Zeiger, richtig?
Falsch. "array" ist ein Feld von Zeigern! Das ist der Unterschied. Und damit ist auch klar, dass der Code geht: Du weist *einem* der Zeiger aus dem Array den Zeiger 'temp' zu -- kein Problem.
Müsste ich eigentlich nicht nach jedem neuen Schleifen durchlauf "delete temp" machen?
Das wäre wahrscheinlich keine so gute Idee, denn dann könntest Du auf das so erzeugte Objekt ja nicht mehr zugreifen, das ist aber ja höchstwahrscheinlich noch irgendwo im Code beabsichtigt (und in dem Array stünde dann ja ein ungültiger Zeiger, also ein Zeiger, der auf nicht reservierten Speicher zeigt).
Allerdings stimmt es schon: wenn die Objekte nicht mehr gebraucht werden, sollten sie freigegeben werden.
-
Mammal *array[4]; //lies: array ist ein Array (größe 4) von Zeigern auf Mammal. Mammal *temp; //lies: temp ist ein Zeiger auf Mammal.array[0]ist das erste element des arrays. da das array ein array von zeigern auf Mammal ist, ist das erste element von array ein zeiger auf Mammal. klar bis jetzt?array[i]ist das i-te element des arrays. und das i-te element eines arrays von zeigern auf Mammal ist... ein zeiger auf Mammal!array[i] = temptemp ist ein zeiger auf Mammal.array[i]ist ein zeiger Mammal. du weist hier also einem zeiger auf Mammal einen zeiger auf Mammal zu. was ist ein zeiger auf Mammal? eine variable, die die adresse eines Mammals beinhaltet. array[i] beinhaltet jetzt also die adresse eines Mammal, nämlich jenes Mammals, dessen adresse auch in temp steht.Und nun will ich dem einem Manmal Zeiger (array) was übergebn. Was übergeb ich hier den eigentlich?
du übergibst hier gar nichts, du weist zu.
Übergeb ich hier den Inhalt von "temp" oder übergeb ich die Adresse von "temp"? Eigentlich übergebe ich doch die Adresse, weil "temp" ohne "*" --> Adress oder?
ein zeiger auf X ist eine variable, die eine adresse (eines X-objektes) beinhaltet. eine varibale hat selbst eine adresse, d.h. ein zeiger hat ebenfalls eine adresse. weiter gedacht: ein da ein "zeiger auf X" selbst eine adresse hat, kann man diese adresse auch wo speichern: in einem zeiger auf einne "zeiger auf X". so in etwa kannst du dir
arrayvorstellen.So aber ich hab mal früehr gelernt das die Klammern "[ ]" den jeweiligen Zeiger dereferenzieren, also übergebe ich jeztt dem dereferenzierten Zeiger array[i] eine Adresse. Mh aber das kann doch nicht gehen oder? Aber es geht.
du dereferenzierst den zeiger ja tatsächlich. nur ist array kein einfacher zeiger, sondern ein zeiger auf (in diesem fall) mehrere zeiger (nämlich 4) auf Mammal.
du hast am schluss also in deinem array vier zeiger, die auf vier verschiedene Mammals zeigen gespeichert.
Müsste ich eigentlich nicht nach jedem neuen Schleifen durchlauf "delete temp" machen? Weil sonst entstehen doch Speicherlücken oder? Aber das ist halt ein Buchbeispiel und ich vertrau dem mal? Wenn man nicht deleten muss dann erklärt mir doch bitte warum, meiner Meinung nach muss man deleten.
deleten kannst du dann mit
for (int i = 0; i < 4; ++i) delete array[i];wahrscheinlich solltest du dir aber einfach nochmal das kapitel in deinem buch durchlesen, das kann dir das sicher viel besser erklären als ich

die C++ FAQ hier bietet AFAIR auch einen beitrag zu zeigern.
/edit: shit, zu spät

-
statt jedes element einzeln zu deleten,warum nicht einfach
delete[] array;nehmen?
-
abend schrieb:
statt jedes element einzeln zu deleten,warum nicht einfach
delete[] array;nehmen?
Weil das nicht klappt?! 'delete[]' ruft nicht für jedes Element eines Felds 'delete' auf sondern es zerstört ein dynamisches Feld (klappt hier also von vornherein nicht) und ruft evtl. für jedes Element noch einen Destruktor auf.
-
Also ich habs mit den Zeigern jetzt glaub schon gecket.
int value[5]; //value[1-4] ist eine Variable in die man int Zahlenwerte reinschreiben kann. int *array[5]; //array[1-4] ist eine Variable in die man Adressen von int Variablen reinschreiben kann. int *p; //p ist eine Variable in die man eine Adresse von einer int Variable reinschreiben kann. array[0]=&value[0]; //array[0] ist nicht dereferenziert; array[0] nimmt die Adresse von value[0] auf. int p=&value[0]; //p ist nicht dereferenziert; p nimmt die Adresse von value[0] auf. cout << *array[0] << endl; //array[0] ist dereferenziert; array[0] gibt den Inhalt von value[0] aus. cout << *p << endl; //p ist dereferenziert; p gibt den Inhalt von value[0] aus.Das was "abend" da aufgerufen hat war doch so gemeint, das hier geht nicht:
array[0]=new int; array[1]=new int; array[2]=new int; array[3]=new int; delete []array;Aber das hier würde doch gehen, wenn ein Zeiger auf ein großes Feld zeigt?
array[0]=new int[5000]; array[1]=new int[5000]; array[2]=new int[5000]; array[3]=new int[5000]; delete []array[0]; delete []array[1]; delete []array[2]; delete []array[3];Dankeschön schon mal im Voraus.
-
perfekt

-
Fast es ist jedesmal array 0-4 und nicht 1-4, oder?
-
Shinja schrieb:
Fast es ist jedesmal array 0-4 und nicht 1-4, oder?
Ja.
Den Arrays werden in der Form:
typ[anzahl]
geschrieben, und der Bereich ist dann 0..(anzahl-1)cu André