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

Käsekönig

1x Contest-Sieger

  • »Käsekönig« ist der Autor dieses Themas
  • Private Nachricht senden

1

07.05.2012, 20:58

std::list Frage

Ich verwende eine std::list, um all meine Einheiten in meinem Spiel darin zu speichern. Es funktioniert alles wunderbar und so wie ich es mir vorstelle, aber mir ist nicht ganz klar, was ich da eigentlich mache. :S

Hier ein fiktiver Codeausschnitt dazu:

Main-Datei:

C-/C++-Quelltext

1
2
3
4
5
6
CMainClass MainClass;

CEinheit Einheit1;    // Eine Einheit erzeugen
Einheit1.SetWerte ();   // Irgendwelche Werte setzen

MainClass.NeueEinheit (Einheit1);   // In die Liste übergeben


Datei, wo die Klasse MainClass drinnen ist:

C-/C++-Quelltext

1
2
3
4
5
6
7
std::list <CEinheit> Einheiten_Liste;   // Membervariable

int MainClass::NeueEinheit (CEinheit &Einheit)
{
  Einheiten_Liste.push_back (Einheit);
  return 0;
}


Mein Problem dabei ist, dass ich ja eine Liste vom Typ CEinheit erzeuge. Das is eine Klasse, mit allerhand Variablen und Funktionen. Jetzt übergeb ich meiner Hilfsfunktion aber eine Referenz und geb diese Referenz dann in meine Liste (also im Prinzip ist die Referenz ja nur ein Spiegelbild, bzw. auch ein Zeiger, der auf das Original zeigt). Aber wenn ich das jetzt in die Liste gebe, wird dann nicht intern in der Liste eine Variable vom Typ CEinheit erstellt und alles rein kopiert? Ist das nicht relativ langsam? Vielleicht kann mir da jemand helfen, wo ich gerade auf der Leitung steh.

2

07.05.2012, 21:44

Ein Zeiger? Nicht doch die Adresse? Oder hab ich' s gerade? xD
Das mit dem intern erstellen: Wie kommst du darauf?

MfG
Check

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

3

07.05.2012, 21:50

Ja, es wir eine Kopie erstellt.
Du könntest eine liste mit std::unique_ptr<CEinheit> verwenden und den Speicher dynamisch anfordern(unique_ptr sorgt dafür, dass es wieder freigegeben wird). Dann wird immer nur der intelligente Zeiger kopiert und nicht die ganze Einheit.

Du kannst es natürlich auch erstmal so lassen bis du Performanceprobleme bekommst. Schreib einfach nen Kommentar dazu, indem steht, dass du dort noch optimieren kannst.

Die Anzahl der Funktionen ist für die größe der Instanz übrigens egal. Die hängt nur von den Variablen ab.(kannst du ja mal mit sizeof ausprobieren ;))
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

h3nryjk

Frischling

Beiträge: 13

Wohnort: 127.0.0.1 - Mi casa es tu casa

Beruf: Student

  • Private Nachricht senden

4

07.05.2012, 21:53

Hey Käsekönig,

std::list.push_back(Type& v);
ist AFAIK eine "call by reference" - Funktion. Der Funktion wird also ein Objekt per Referenz übergeben,
es wird also zunächst keine Kopie des Objektes angelegt; das ganze funktioniert also so ähnlich, als
würdest du der Funktion einen Pointer übergeben, der dann dereferenziert wird.
Um jedoch das Objekt in die Liste einreihen zu können, muss jedoch eine Kopie erstellt werden.
Wird der Block, in dem sich das ursprüngliche Objekt befindet, verlassen, stünde ansonsten in der Liste
nur ein Zeiger, der auf eine leere Position im Speicher zeigt.

Btw. ist es überhaupt nicht schlimm, wenn ein Objekt mit (relativ) vielen Variablen kopiert bzw.
in eine Liste eingefügt wird; der Prozessor kann sowas ab ;)
Lediglich beim Iterieren durch die Liste und würde ich mir über so etwas Gedanken machen.

Hoffe das hat dir irgendwie weiter geholfen ;)

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

5

07.05.2012, 22:00

Es geht nicht darum was bei der Übergabe passiert, sondern was in der Methode selbst passiert. Dort wird sehr wohl der Kopierkonstruktor aufgerufen. Er hat also recht.
Das Itererieren durch eine doppelt verkettete Liste ist nicht langsamer als bei Vectoren z.B.
Die Nachteile sind eher der höhere Speicherbedarf(2 Zeiger pro Element), dass für jedes Element new aufgerufen werden muss(was langsam sein kann wenn man eine große Anzahl von Elementen anfügt) und, dass man kein Randomaccess hat.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

07.05.2012, 22:22

C-/C++-Quelltext

1
2
3
4
5
int MainClass::NeueEinheit (CEinheit &Einheit)
{
  Einheiten_Liste.push_back (Einheit);
  return 0;
}

Das ist übrigens die schlimmste Art zu programmieren schlechthin. Eine einzige Methode wird in eine 2-Zeile-Methode gekapselt, die immer 0 zurückgibt? Wozu? Erstens macht es den Code unnötig größer, zweitens unverständlich (nicht wegen dem Denglisch, aber das hilft sicher auch nicht so viel... "MainClass::NeueEinheit") und drittens müsste der Aufrufer den Return-Value der Methode für irgendwas verwenden können oder ihn auf irgendwas testen, was aber offenbar keinen Sinn macht.

@NachoMan:
Sicher dass eine Iteration über eine verkettete Liste nicht doch etwas langsamer ist als bei einem Vektor? Mir war so als hätte es hier schon mehrere Themen gegeben, wo genau dieser Unterschied doch spürbar war.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Käsekönig

1x Contest-Sieger

  • »Käsekönig« ist der Autor dieses Themas
  • Private Nachricht senden

7

07.05.2012, 22:24

Wenn ich das also richtig verstanden habe, übergibt man der Liste mit push_back eine Adresse, um das Objekt dann der Liste hinzuzufügen (was in der push_back Funktion geschieht), wird das ganze Objekt kopiert!?
Anders als dass es kopiert wird, kann es nicht gehen, weil ich nur einmal eine Variable vom Typ CEinheit erstelle, die Werte ändere und beliebig oft in die Liste gebe, um mehrere Einheiten zu erhalten. Deshalb kann ich auch nicht die Zeiger in eine Liste speichern, wenn du das gemeint hast, NachoMan.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

07.05.2012, 22:25

Wenn man Zeiger speichert, dann erzeugt man auch normalerweise immer neue Instanzen und fummelt nicht an einer bestehenden rum um daraus eine neue zu machen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Käsekönig

1x Contest-Sieger

  • »Käsekönig« ist der Autor dieses Themas
  • Private Nachricht senden

9

07.05.2012, 22:31

Das ist übrigens die schlimmste Art zu programmieren schlechthin. Eine einzige Methode wird in eine 2-Zeile-Methode gekapselt, die immer 0 zurückgibt? Wozu? Erstens macht es den Code unnötig größer, zweitens unverständlich (nicht wegen dem Denglisch, aber das hilft sicher auch nicht so viel... "MainClass::NeueEinheit") und drittens müsste der Aufrufer den Return-Value der Methode für irgendwas verwenden können oder ihn auf irgendwas testen, was aber offenbar keinen Sinn macht.


Ich hab sie deshalb gekapselt, weil ich die Liste privat halten wollte. Mag sein, dass das keinen Sinn ergibt, das kann ich ja immer noch ändern. Und mir ist klar, dass man sich über meinen Codestil beschweren kann (den Mischmasch aus Deutsch und Englisch und sonstigen unnötigen Sachen), doch bei mir liegt im Vordergrund das Ergebnis, und nicht wie ich es erreiche. Natürlich versuch ich, das halbswegs gut zu machen, aber um das alles perfekt hin zu bekommen, fehlt mir halt einfach die Erfahrung. ;)

Ja ich speicher ja eben keine Zeiger, sondern das ganze Objekt als solches.

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

10

07.05.2012, 23:09

Das Itererieren durch eine doppelt verkettete Liste ist nicht langsamer als bei Vectoren z.B.

Das bezweifle ich. Wenn man durch die Liste iteriert springt man für jedes Element an eine komplett andere Stelle im Adressraum, macht den Cache also völlig nutzlos. Bei Vektoren wird er praktisch perfekt genutzt, und der Compiler kann durch den Random access sicher noch einiges optimieren.

Ich persönlich würde von std::list grundsätzlich abraten.
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

Werbeanzeige