Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

22.05.2008, 18:35

dynamisches (Array) Instanz Zeiger

Hallo,
Hab etwas rumprobiert mit Zeigern und bin auf folgendes Problem gestoßen. Ich hab eine dynamische Instanz als einen (mehrere) Zeiger auf den Heap und möchte diesen nun an eine Funktion übergeben

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CRaumschiff *spieler=NULL;
spieler= new CRaumschiff[Anzahl];

for (int i=0;i<Anzahl;i++)
{
    cout<<"Spieler:"<<i+1<<endl;
    spieler[i].init ();
}

    spielerausgeben(&spieler, Anzahl);

    delete [] spieler;
    spieler=0;

return 0;   
}       

void spielerausgeben (CRaumschiff *spieler[],int Anzahl)
{
    for (int i=0;i<Anzahl;i++)
    {   
        spieler[i].zeigedaten();//hier sitzt der Fehler habs auch mit -> schon probiert

    }
}


Das Beispiel ist ähnlich wie im Buch „C++ für Spieleprogrammierer“ und ergibt jetzt keinen großen Sinn, aber wie gesagt hab nur rumprobiert.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

22.05.2008, 18:56

Mach aus:

C-/C++-Quelltext

1
spielerausgeben(&spieler, Anzahl);


einfach

C-/C++-Quelltext

1
spielerausgeben(spieler, Anzahl); 


Und aus:

C-/C++-Quelltext

1
void spielerausgeben (CRaumschiff *spieler[],int Anzahl) 


ein

C-/C++-Quelltext

1
void spielerausgeben (CRaumschiff *spieler,int Anzahl) 
@D13_Dreinig

3

22.05.2008, 19:22

Jo funktioniert Danke
Also versteh ich das richtig da "spieler" schon ein zeiger ist und somit eine Adresse. Hatte ich vorhin sozusagen die Adresse der Adresse übergeben?

DasBlub

Alter Hase

Beiträge: 802

Wohnort: Schweiz

Beruf: Programmierer

  • Private Nachricht senden

4

22.05.2008, 19:22

Re: dynamisches (Array) Instanz Zeiger

Zitat von »"Danda"«

C-/C++-Quelltext

1
2
CRaumschiff *spieler=NULL;
spieler= new CRaumschiff[Anzahl];




dies ist unschön. schöner wäre:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
CRaumschiff*  pPlayer; // variable definieren


pPlayer = (CRaumschiff*)malloc(sizeof(CRaumschiff)); // speicher allokieren

pPlayer = new CRaumschiff();
...

if(pPlayer) // loeschen, falls nicht null

  delete pPlayer;


oder für mehrere (= array):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int           iPlayerSize;
CRaumschiff**  pPlayer; // variable definieren


pPlayer      = (CRaumschiff*)malloc(sizeof(CRaumschiff) * iPlayerSize); // speicher allokieren (fuer array)

for( int i = 0; i < iPlayerSize; i++ ) {
  pPlayer[i] = (CRaumschiff*)malloc(sizeof(CRaumschiff)); // speicher allokieren (fuer array)

  pPlayer[i] = new CRaumschiff(); // player anlegen

}

...

if(pPlayer) { // loeschen, falls nicht null

  for( int i = 0; i < iPlayerSize; i++ ) {
    if(pPlayer[i]) // loeschen, falls nicht null

      delete pPlayer[i];
  }
  delete[] pPlayer; // array loeschen

}

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

22.05.2008, 19:32

Das ist unschön... :shock:

Ich kommentier das mal:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
CRaumschiff*  pPlayer;

pPlayer = (CRaumschiff*)malloc(sizeof(CRaumschiff)); 
pPlayer = new CRaumschiff(); // Memory leak

...

if(pPlayer) // total unnötig, da delete auf einen 0-Zeiger sicher ist

  delete pPlayer; 


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int           iPlayerSize;
CRaumschiff**  pPlayer; // Warum denn ein Doppelzeiger? Ist doch total fehl am Platz.


pPlayer      = (CRaumschiff*)malloc(sizeof(CRaumschiff) * iPlayerSize);
for( int i = 0; i < iPlayerSize; i++ ) {
  pPlayer[i] = (CRaumschiff*)malloc(sizeof(CRaumschiff)); 
  pPlayer[i] = new CRaumschiff(); // memoryleak

}

...

if(pPlayer) { // ist immer noch unnötig, s.o.

  for( int i = 0; i < iPlayerSize; i++ ) {
    if(pPlayer[i]) // Ist auch unnütz ohne Ende

      delete pPlayer[i];
  }
  delete[] pPlayer; // array loeschen

} 
@D13_Dreinig

DasBlub

Alter Hase

Beiträge: 802

Wohnort: Schweiz

Beruf: Programmierer

  • Private Nachricht senden

6

22.05.2008, 20:12

wiso gibt das einen memoryleak bei

C-/C++-Quelltext

1
pPlayer = new CRaumschiff();

??
doppelzeiger habe ich, da es ja ein ARRAY auf ZEIGER ist...

aber auch ich bin nicht der beste in pointern, und lasse mich gerne eines besseren belehren

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

22.05.2008, 20:26

Zitat von »"TheWinner"«

wiso gibt das einen memoryleak bei

C-/C++-Quelltext

1
pPlayer = new CRaumschiff();

??


Weil du zweimal Speicher reservierst aber nur einmal freigibst.

Zitat von »"TheWinner"«


doppelzeiger habe ich, da es ja ein ARRAY auf ZEIGER ist...


Was er wollte war aber ein Array von CRaumschiff-Objekten und kein Zeiger auf Zeiger auf CRaumschiff-Objekte.
@D13_Dreinig

8

22.05.2008, 20:30

Warum das nen Leak gibt? Weil erst malloc nen Speicher anfordert. Aber da es eine C Funktion ist, keinen Konstruktor für das Objekt aufruft. Dann reservierst du nochmal neuen Speicher und rufst diesesmal die Konstruktor auf ;) Dabei geht dir der Zeiger auf den alten Speicher verloren (du merkst ihn dir nicht mehr), wodurch es nichtmehr möglich ist, free darauf aufzurufen.

Das was unschön ist, ist die init-Funktion. Mach lieber nen Konstruktor und ruf das dann so auf:

C-/C++-Quelltext

1
CRaumschiff* ptr_player_arr(new CRaumschiff[Anzahl](Parameter));
... Schreib dir beim Variablennamen ruhig dazu, das es sich um einen Array handelt(delete ist undefiniert bei array, delete [] ist korrekt). Parameter durch die von dir gewünschten Parameter für den Konstruktor ersetzen.
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

9

22.05.2008, 20:35

Zitat von »"Deviloper"«

Warum das nen Leak gibt? Weil erst malloc nen Speicher anfordert. Aber da es eine C Funktion ist, keinen Konstruktor für das Objekt aufruft. Dann reservierst du nochmal neuen Speicher und rufst diesesmal die Konstruktor auf ;) Dabei geht dir der Zeiger auf den alten Speicher verloren (du merkst ihn dir nicht mehr), wodurch es nichtmehr möglich ist, free darauf aufzurufen.

Das was unschön ist, ist die init-Funktion. Mach lieber nen Konstruktor und ruf das dann so auf:

C-/C++-Quelltext

1
CRaumschiff* ptr_player_arr(new CRaumschiff[Anzahl](Parameter));
... Schreib dir beim Variablennamen ruhig dazu, das es sich um einen Array handelt(delete ist undefiniert bei array, delete [] ist korrekt). Parameter durch die von dir gewünschten Parameter für den Konstruktor ersetzen.


Netter Versuch! :idea: Aber vielleicht bin ich auch einfach nicht auf dem neuesten Stand des Standards! :p

Gemeint war vermutlich die ganze Zeit das:

C-/C++-Quelltext

1
2
3
4
CRaumschiff* p = ( CRaumschiff* )malloc( sizeof( CRaumschiff ) * 100 ); // nehmen wir mal 100


for ( unsigned i = 0; i < 100; ++i )
    new ( &i[ p ] ) CRaumschiff( parameter ... );
@D13_Dreinig

10

23.05.2008, 13:22

Man kann sich das Leben auch unnötig schwer machen ;)
Wir sind doch hier in C++ (cout lässt mich das annehmen), warum nicht "einfach" die Mittel benutzen, die einem schon freihaus geliefert werden. Vor allem, da man hier im Großen auf Pointer verzichten kann und Referenzen verwenden sollte.

Exemplarischer (voll funktionsfähiger) Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
#include <vector>

// ------------------------------------------------------------------

class Raumschiff
{
    std::string name_;   // Exemplarisch, damit die Klasse etas Leben bekommt


public:
    Raumschiff(std::string const& name)
        : name_(name)
        { }
    std::string getName() const { return name_; }
    void setName(std::string const& name) { name_ = name; }
};
// ------------------------------------------------------------------

void ausgeben(Raumschiff const&);   // Prototyp

// ------------------------------------------------------------------

int main()
    {
        // std::vector anlegen und mit Raumschiffen "bevölkern"

        std::vector<Raumschiff> raumschiffe;
        raumschiffe.push_back(Raumschiff("Enterprise"));
        raumschiffe.push_back(Raumschiff("Heart of Gold"));
        raumschiffe.push_back(Raumschiff("Executor"));

        // Durch die gespeicherten Raumschiffe iterieren und die

        //  Objekte mittels Funktion 'ausgeben' ausgeben.

        std::vector<Raumschiff>::const_iterator iter = raumschiffe.begin();
        for( ; iter != raumschiffe.end(); ++iter) {
            ausgeben(*iter);
        }

        return EXIT_SUCCESS;
    }
// ------------------------------------------------------------------

void ausgeben(Raumschiff const& schiff)
    {
        std::cout << "Raumschiff: " << schiff.getName() << std::endl;
    }


Sicher, das kann man noch schöner bewerkstelligen - Kommt mir das nur so vor, oder habe ich gerade ein deja vu?

Grüße... Heiko

Werbeanzeige