# C++ Speicher allkokieren, Konstruktor, Destruktor



## WallaceXIV (14. Juni 2011)

Ich hab mir was zusammen programmiert, aber ich habe jetzt ein Problem damit, ich blick nicht genau durch was ich da eigentlich mache.

Ich lese eine Textdatei mit mehreren Zeilen und verschiedenen Werten ein.

Am Anfang der Testdatei habe ich die Anzahl der Zeilen bzw. Datensätze gespeichert.




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Nach dieser Zahl richtet sich die Größe des allokierten Speichers


```
class Klasse 1
{
    private:
           ....

    public:
           Klasse1() {} // Konstruktor
           ....

};  // Ende Klasse1


class Klasse2
{
    private:
            int Anzahl;
    public:
            Klasse1 *Test; // inititalisiert Konstruktor der Klasse1 mit dynamischen Werten
            Klasse2() {DatenEinlesen();} // Konstruktor
            ~Klasse2() {delete[] Test;} // Destruktor
            void DatenEinlesen();
            

};  // Ende Klasse2

void Klasse2::DatenEinlesen()
{
   .....
   ifstream lesen("blabla.txt");
   lesen >> Anzahl;
   Test = new Klasse1[Anzahl];
   
   for (int i = 0; i < Anzahl; i++)
   {
      ....
      ....
      ....
   }

   lesen.close();
}
```
Jetzt will ich einen neuen Datensatz hinzufügen, aber der Speicher wurde  ja schon allokiert. Neu allokieren bringt einen Fehler, genau so wie  ohne neu allokieren und einfach so hinzufügen.

Wie funktioniert das genau?


----------



## Crysis nerd (14. Juni 2011)

Also ich verstehe dich gerade nicht komplett.
Also so wie ich das sehe, versuchst du in Klasse 2 ein Array von Objekten der Klasse 1 zu speichern? Klasse 1 enthält dann Daten, die in der Datei stehen (Name, etc..).

Wenn dem so ist, guck dir mal Stl Container an an. STL Containers - C++ Reference
Das sind alle Container, wichtig für dich sind *vector und list*. Also ich verplane immer wieder wofür was war, bei einem konnte man keine Datensätze in der Mitte einfügen, sondern nur am Anfang oder Ende.

Jedenfalls kann man dann immer Datensätze hinzufügen.
Beispiel:

```
ifstream lesen("blabla.txt");
   lesen >> Anzahl;
   std::vector<Klasse1> Test;
   for(blabla)
   {
       Klasse1 tmp = new Klasse1(KonstruktorZeug);
       Test.push_back(tmp);
```

So müsste das dann aussehen. Ich hoffe ich hab das Problem verstanden..

mfg
Lukas


----------



## WallaceXIV (14. Juni 2011)

Also ich initialisiere den Konstruktor der Klasse1 mit den eingelesenen Daten aus der Textdatei. Ich verstehe es aber selbst nicht zu 100%. Das gab es so auf irgendeiner Internetseite, ich habe es halt auf meine Bedürfnisse angepasst. Es funktioniert auch soweit, nur das anfügen von Daten bzw. dann später das löschen (noch nicht versucht) funktioniert nicht.


----------



## Fragile Heart (15. Juni 2011)

Das Anfügen von Daten ist in deinen Konstrukt immer, erzeugen eines neuen Arrays mit n+x Objekten (n sind die Bestandsdatensätze und x die Anzahl an neuen Datensätzen), dann kopierst du den Inhalt des alten an den Anfang des neuen Arrays und die neuen dadrüber. Soweit klar?

Hast du dich schonmal mit dynamischen Datenstrukturen beschäftigt? Das ist genau das was du hier bräuchtest.


----------



## WallaceXIV (15. Juni 2011)

Ja hab mich damit schon beschäftigt. In C ist das auch kein größeres Problem, nur mit C++ tu ich mich da schwer. Mir liegt die objektorientierte Denkweise nicht so.  

Soll ich neuen Speicher allkokieren? Also quasi temporär zwischenspeichern und dann das Original-Feld überschreiben?


----------



## Fragile Heart (15. Juni 2011)

WallaceXIV schrieb:


> Ja hab mich damit schon beschäftigt. In C ist das auch kein größeres Problem, nur mit C++ tu ich mich da schwer. Mir liegt die objektorientierte Denkweise nicht so.
> 
> Soll ich neuen Speicher allkokieren? Also quasi temporär zwischenspeichern und dann das Original-Feld überschreiben?


 
Du kannst im Prinzip in C++ genauso arbeiten wie bei C! Nur wenn virtuelle Funktionen im spiel sind, dann wäre etwas zu beachten. Also wenn du das ganze schon mal in C gemacht hast, dann einfach übertragen.

Was musst du machen?  Wie gesagt im Endeffekt ist das recht einfach. Du musst ein neues Array erzeugen, das umsoviel größer ist wie du neue Elemente hast. Nemmen wir an du hast eine Array mit n Elemente und willst x Elemente hinzufügen, dann ist die neue Größe n+x. 

newArray = new Type[n+x];

Dann kopierst du den Inhalt des alten in das neue Array (einfache for-schleife oder memcpy), und ab n kommen dann die neuen Elemente (auch wieder einfach per for schleife oder memcpy). soweit verstanden?


----------



## WallaceXIV (15. Juni 2011)

Jo hab ich verstanden, Danke. Ich probiere es morgen aus und gebe Bescheid. Der nächste Schritt ist dann noch löschen eines Datensatzes, da muss ich mit noch was überlegen wenn zwischen drin was gelöscht wird.


----------



## Crysis nerd (15. Juni 2011)

wenn schon memcpy, geht schneller 
Aber mal ne frage: warum wird hier kein dynamisches Array benutzt? Also list oder vector, wie ich schon vorgeschlagen habe..


----------



## WallaceXIV (15. Juni 2011)

Das Array ist doch dynamisch. Es wird doch erst zur Laufzeit angelegt.


```
Test = new Klasse1[Anzahl];
```


----------



## bingo88 (15. Juni 2011)

Er meint eigentlich eine dyn. Datenstruktur, zum Beispiel ne Liste. Da kannst du dann einfach Elemente hinzufügen und wieder entfernen, ohne dich um den eigentlichen Speicher zu kümmern.


----------



## WallaceXIV (16. Juni 2011)

Das wäre zu viel Aufwand für das kleine Programm. Es soll am Ende nur funktionieren.


----------



## Fragile Heart (16. Juni 2011)

WallaceXIV schrieb:


> Das Array ist doch dynamisch. Es wird doch erst zur Laufzeit angelegt.


Also nur zur Info für dich, wenn du ein Array mit der größe n erzeugst, dann ist dieser auch nur so große das es Platz für n Elemente hat. ->n*memsize... 

Ergo ist da hinter etwas irgendetwas anderes und wenn du das überschreibst, dann beginnt der Spaß erst richtig! 



bingo88 schrieb:


> Er meint eigentlich eine dyn. Datenstruktur, zum Beispiel ne Liste. Da kannst du dann einfach Elemente hinzufügen und wieder entfernen, ohne dich um den eigentlichen Speicher zu kümmern.


 Naja, auch ein dynamischer Array (und um was anderes geht es hier ja auch nicht) ist eine dynamische Datenstruktur.  Sie hat zwar nicht die Vorteile beim hinzufügen/entfernen wie eine Liste, dafür aber schnellen Element Zugriff. 



WallaceXIV schrieb:


> Das wäre zu viel Aufwand für das kleine Programm. Es soll am Ende nur funktionieren.


Was soll ich hier drauf noch antworten? Wir reden hier, ohne Prüfung, im besten Fall von einen vier Zeiler! Im wahrsten Sinne des Wortes! Sorry, aber wenn dir das zu viel ist, dann tut es mir leid!


----------



## WallaceXIV (16. Juni 2011)

Fragile Heart schrieb:


> Was soll ich hier drauf noch antworten? Wir reden hier, ohne Prüfung, im besten Fall von einen vier Zeiler! Im wahrsten Sinne des Wortes! Sorry, aber wenn dir das zu viel ist, dann tut es mir leid!


 
Ruhig bleiben Herzchen, ich meine eine Liste oder ein Baum wären zu viel Aufwand für das kleine Programm.


----------



## Fragile Heart (16. Juni 2011)

WallaceXIV schrieb:


> Ruhig bleiben Herzchen, ich meine eine Liste oder ein Baum wären zu viel Aufwand für das kleine Programm.


 
Nun ja, dann solltest du ja jetzt wissen was du zu machen hast. Diese Handvoll Zeilen sollten ansich kein Problem sein und es ist ein schöner Lerneffekt.


----------



## bingo88 (16. Juni 2011)

Fragile Heart schrieb:


> Naja, auch ein dynamischer Array (und um was anderes geht es hier ja auch nicht) ist eine dynamische Datenstruktur.  Sie hat zwar nicht die Vorteile beim hinzufügen/entfernen wie eine Liste, dafür aber schnellen Element Zugriff.


 Ja, ich hatte als alter Java-Programmierer auch ne ArrayList (also keine verkettete Liste) im Kopf


----------



## Fragile Heart (16. Juni 2011)

bingo88 schrieb:


> Ja, ich hatte als alter Java-Programmierer auch ne ArrayList (also keine verkettete Liste) im Kopf


 
Achso heißt das in Java. Versuche Java wann immer es geht zu meiden.


----------



## WallaceXIV (16. Juni 2011)

Hier stand mist.


----------



## WallaceXIV (16. Juni 2011)

Fragile Heart schrieb:


> Nun ja, dann solltest du ja jetzt wissen was du zu machen hast. Diese Handvoll Zeilen sollten ansich kein Problem sein und es ist ein schöner Lerneffekt.



Ich probiers dann gleich aus. Danke.

EDIT: Ein Problem ist noch, ich habe die Daten ja alle in den Konstruktor geladen. Den Konstruktor müsste ich ja jetzt wieder nehmen um den temporären Speicher zu allokieren. Der Zeiger muss doch vom Typ des Konstruktors sein oder nicht?



```
...

Klasse1() {} // Konstruktor

...

Klasse1 *Test; // inititalisiert Konstruktor der Klasse1 mit dynamischen Werten

...

Test = new Klasse1[Anzahl];
```


----------



## Crysis nerd (16. Juni 2011)

Ihr seid Hammer Leute 
Ja, Java is doof
Ja, es ist kaum Arbeit. Listen sind einfach total einfach zu nutzen (nur Schleifendurchläufe brauchen ein wenig Einarbeitungszeit )

Tipp: Nimm jetzt verdammt nochmal std::list  !! oder vector, wenn du bock hast.
Es lößt einfach alle deinen Array Probleme. Arrays nimmt man nur wenn man extrem performance orientiert ist, wenn man den ganzen Programmablauf über die Größe des Arrays nich änder oder wenn man alternativen noch nicht kennt 

viel glück noch bei deinem teil


----------



## WallaceXIV (16. Juni 2011)

Crysis nerd schrieb:


> Ihr seid Hammer Leute
> Ja, Java is doof
> Ja, es ist kaum Arbeit. Listen sind einfach total einfach zu nutzen (nur Schleifendurchläufe brauchen ein wenig Einarbeitungszeit )
> 
> ...



Nicht so aggro.


----------



## Fragile Heart (16. Juni 2011)

WallaceXIV schrieb:


> EDIT: Ein Problem ist noch, ich habe die Daten ja alle in den Konstruktor geladen. Den Konstruktor müsste ich ja jetzt wieder nehmen um den temporären Speicher zu allokieren. Der Zeiger muss doch vom Typ des Konstruktors sein oder nicht?


Also, wenn man es ganz genau nimmt, dann hat ein Konstruktor keinen Typ (von den Parametern abgesehen  ). Der Konstruktor ist nur eine Funktion, die aufgerufen wird wenn du ein Instanz der Klasse erzeugst. 

Was du möchtest ist doch folgendes


```
class Klasse2
{
Klasse1 *Test; // Das hier ist nur eine Membervariable und kein Konstruktor ;)
...

void Add(Klasse1 *neuesObjekt)
{
Klasse1* tempPointer = new Klasse1[Anzahl + 1];
(kopieren und son Zeugs)
delete Test;
Test = tempPointer;
} // void Add()
} // class Klasse2
```
Soweit verständlich?


----------



## WallaceXIV (16. Juni 2011)

C++ und ich werden keine Freunde. Kannst du mir das mal erklären was du da machst und warum, bitte so als hätte ich keine Ahnung von Programmieren.


----------

