Programmieren - alles kontrollieren 4.941 Themen, 20.708 Beiträge

c++: frage zu arrays

Yves3 / 11 Antworten / Baumansicht Nickles

hallo


ich hab mal wieder eine frage zu c++ ;-) der erste quellcode ist aus meinem programmierbuch. warum wird dort der zeiger "pCat" verwendet? was ist an meiner lösung(source 2) anders? warum wurde das im buch nicht so gelöst?


danke für alle antworten!


<b>source 1:</b>


#include <iostream.h>


class CAT
{
public:
 CAT() { itsAge = 1; itsWeight = 5; }
 ~CAT();
 int GetAge() const { return itsAge; }
 int GetWeight() const { return itsWeight; }
 void SetAge(int age) { itsAge = age; }


private:
 int itsAge;
 int itsWeight;
};


CAT::~CAT()
{
// cout << "Destruktor aufgerufen!\n";
}


int main()
{
 CAT * Family = new CAT[500];
 int i;
 CAT * pCat;
 <b> 


for(i = 0; i<500 ; i++)
 {
  pCat = new CAT;
  pCat->SetAge(2*i +1);
  Family[i] = *pCat;
  delete pCat;
 }</b>


 for(i = 0; i<500; i++)
  cout << "Katze#" << (i+1) << ": " << Family[i].GetAge() << endl;


 delete [] Family;


 return 0;
}


<b>source 2</b>


#include <iostream.h>


class CAT
{
public:
 CAT() { itsAge = 1; itsWeight = 5; }
 ~CAT();
 int GetAge() const { return itsAge; }
 int GetWeight() const { return itsWeight; }
 void SetAge(int age) { itsAge = age; }


private:
 int itsAge;
 int itsWeight;
};


CAT::~CAT()
{
// cout << "Destruktor aufgerufen!\n";
}


int main()
{
 CAT * Family = new CAT[500];
 int i;
 <b>
 for(i = 0; i<500 ; i++)
 {


  Family[i].SetAge(2*i +1);


 }</b>


 for(i = 0; i<500; i++)
  cout << "Katze#" << (i+1) << ": " << Family[i].GetAge() << endl;


 delete [] Family;


 return 0;
}

bei Antwort benachrichtigen
Yves3 Nachtrag zu: „c++: frage zu arrays“
Optionen

html scheint nur bei antworten zu funktionieren :-(

bei Antwort benachrichtigen
vergisses Yves3 „c++: frage zu arrays“
Optionen

Hi Yves3,

Deine Version ist besser, sie geht den direkten und
performanteren Weg, während in der Buchversion
bei jedem Schleifendurchlauf ohne zwingenden Grund
ein Objekt instanziert, kurz verwendet und
danach wieder weggeschmissen wird.

Die Zuweisung
Family[i] = *pCat;
kommt mir sogar bedenklich vor.
Wirft der Compiler hier keinen Fehler aus ?


Gruss, vergisses

bei Antwort benachrichtigen
vergisses Yves3 „c++: frage zu arrays“
Optionen

Hi Yves3,

Die Zuweisung
Family[i] = *pCat;
ist bedenklich, da dort die Speicheradresse,
auf die *pCat zeigt, kopiert wird und in der Folgezeile
das *pCat Objekt wieder gelöscht wird.
Somit verwendet Family[i] eine nicht mehr
allozierte Speicherfläche, und auf die vorher
von Family[i] verwendete Speicherfläche
kann nicht mehr zugegriffen werden.
Dieser Fehler wird wahrscheinlich nicht vom Compiler erkannt,
sondern führt evtl. zu Laufzeitfehlern (Segment Verletzung).

Richtig wäre hier eine Operation, die letzten Endes
die einzelnen Membervariablen itsAge und itsWeight
einzeln kopiert. Die Implementierung könnte durch
durch entsprechende Memberfunktionen wie z. B. getAge/setAge
oder durch Überladung des Zuweisungsoperators = erfolgen.


Gruss, vergisses

bei Antwort benachrichtigen
Yves3 vergisses „Kleine Ergänzung“
Optionen

"Family[i] = *pCat;
ist bedenklich, da dort die Speicheradresse,
auf die *pCat zeigt, kopiert wird und in der Folgezeile
das *pCat Objekt wieder gelöscht wird."

pCat wird doch dereferenziert, es wird also das CAT objekt als wert übergeben und nicht die adresse des zeigers. daher sollte es meiner meinung nach eigentlich nicht bedenklich sein. oder liege ich da falsch?

bis jetzt war in diesem buch ziemlich gut beschrieben, warum etwas so und nicht anders gemacht wird. ich vermute, dass da noch ein "tieferer sinn" dahinter ist.

bitte korrigiere mich, wenn ich da etwas falsch verstanden habe.
danke für deine antwort

bei Antwort benachrichtigen
mr.escape Yves3 „Kleine Ergänzung“
Optionen

Die einwände von vergisses sind falsch und deine version ist definitiv die bessere. Evtl. soll lediglich etwas demonstriert werden und der sinn ergibt sich aus der beschreibung im buch.

mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
Yves3 mr.escape „Kleine Ergänzung“
Optionen

ich hab mir das noch einmal alles genau angeschaut und von vorne bis hinten durchgelesen. es ist ,wie du sagtest, nur als demonstration gedacht. ich bemerkte es nicht, weil es nicht dort steht, wo die analyse des quelltexts normalerweise ist.
es wird erst unter der nächsten überschrift erklährt.

noch einmal danke für die antworten!
gruss yves

bei Antwort benachrichtigen
vergisses Yves3 „Kleine Ergänzung“
Optionen

Sorry, dass ich mich jetzt erst melde, ich war unterwegs.

Deine Aussage, dass ein CAT Object an das Andere zugewiesen
wird, ist richtig.

Meine Ausführungen sind tatsächlich teilweise falsch.
Vergiss die Sache mit den Pointern.
Aber in Bezug auf die Kopieraktion halte ich meine Ausführung
nach wie vor für richtig.
Wird das CAT Objekt mit allen Inhalten oder
wird nur die Referenz kopiert ?

Objekte sind doch zusammengesetzte Datentypen und
Objektvariable letzlich ein Zeiger auf den Beginn
der vom Objekt belegten Speicherfläche.
Wenn ich Datenstrukturen kopieren will, kann ich das
doch auch nicht durch eine einfache Zuweisung tun,
sondern muss jede Membervariable einzeln kopieren, oder ?

Ich werde das Ganze mal austesten und dann berichten,
was dabei rauskam.

Gruss, vergisses

bei Antwort benachrichtigen
mr.escape vergisses „Kleine Ergänzung“
Optionen
Objekte sind doch zusammengesetzte Datentypen und
Objektvariable letzlich ein Zeiger auf den Beginn
der vom Objekt belegten Speicherfläche.
Wenn ich Datenstrukturen kopieren will, kann ich das
doch auch nicht durch eine einfache Zuweisung tun,
sondern muss jede Membervariable einzeln kopieren, oder ?

Das macht normalerweise der kopier-operator, der einfach den speicher brutal kopiert. Damit werden auch die zeiger kopiert und zeigen dann auf die selbe adresse. Das kann gewollt sein, muss aber nicht immer gutgehen! Wenn man einen eigenen kopier-operator definiert, hat man alle aspekte unter kontrolle. Sind keine zeiger in der struktur, reicht aber der einfach (default) memcopy. Ein guter compiler sollte aber bei fehlendem kopier-operator UND zeigern in der struktur warnen (VC6 warnt natürlich nicht! VC7 soll aber angeblich deutlich strenger sein).

mr.escape
"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
vergisses Nachtrag zu: „Kleine Ergänzung“
Optionen

Hallo Leute,

Ihr habt Recht, bitte um Vergebung....

Hier das Testprogramm.
-----------schnipp------------------
#include

class CAT
{
public:
CAT() { itsAge = 0; itsWeight = 0; }
~CAT();
int GetAge() const { return itsAge; }
int GetWeight() const { return itsWeight; }
void SetAge(int age) { itsAge = age; }
void SetWeight(int weight) { itsWeight = weight; }
void print();

private:
int itsAge;
int itsWeight;
};


CAT::~CAT()
{
printf("Destruktor aufgerufen!\\n");
}

void CAT::print()
{
printf("Age=%d:Weight=%d:this=%ld:Adress GetAge=%ld\\n"
,itsAge,itsWeight,this,GetAge);
}


int main()
{
CAT a,b;
a.print();
b.print();
a.SetAge(1);
a.SetWeight(1);
b.SetAge(2);
b.SetWeight(2);
a.print();
b.print();
a=b;
printf("Mal sehen\\n");
a.print();
b.print();

return 0;
}

-----------schnipp------------------
und hier die Ausgaben
-----------schnipp------------------
Age=0:Weight=0:this=1245036:Adress GetAge=4198435
Age=0:Weight=0:this=1245028:Adress GetAge=4198435
Age=1:Weight=1:this=1245036:Adress GetAge=4198435
Age=2:Weight=2:this=1245028:Adress GetAge=4198435
Mal sehen
Age=2:Weight=2:this=1245036:Adress GetAge=4198435
Age=2:Weight=2:this=1245028:Adress GetAge=4198435
Destruktor aufgerufen!
Destruktor aufgerufen!
-----------schnipp------------------
Die Ausgabe von this belegt einwandfrei, dass es
wirklich 2 Objekte sind.
Die einfache Zuweisung hat zum Kopieren ausgereicht.
Interessanterweise existieren die Klassenmethoden aber nur
einmal im Speicher.
Ich muss zugeben, dass ich mehr in C als in C++ Zuhause bin...

Gruss, vergisses

bei Antwort benachrichtigen
mr.escape vergisses „Kleine Ergänzung“
Optionen
Interessanterweise existieren die Klassenmethoden aber nur
einmal im Speicher.

Was ist daran interessant? Diese methode wird mit dem "this" zeiger aufgerufen und weiß damit immer, welche aktuelle instanz zu bearbeiten ist (der compiler macht automatisch "this->" vor die klassenmitglieder, bei mehrdeutigkeiten muß man aber immer noch "this->" davor setzen).

mr.escape
"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
vergisses mr.escape „Kleine Ergänzung“
Optionen

Ich muss mir wohl doch nochmal den Stroustrup reinziehen ;-)
In den letzten Jahren habe ich nur noch sehr wenig mit
C++ gemacht, da alle Welt Java haben wollte.
Jetzt wird es wohl Zeit, die C++ Kenntnisse wieder etwas
aufzufrischen...

Gruss, vergisses

bei Antwort benachrichtigen