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

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

31

01.04.2015, 21:19

Klar sind sie hübscher, aber dafür hat man auch moderneren Code. Man benutzt heutzutage schließlich auch void bar(const std::vector<Foo>& foobar) statt void bar(Foo foobar[])
const std::vector hat allerdings eben auch einen ganz anderen Nutzen als const std::unique_ptr&. Letzterer ist komplett überflüssig. Ein const Raw* ist wesentlich besser geeignet. Es suggeriert bei flüchtigem Blick auch keine Übertragung der Ownership. Ich hoffe "es sieht modern aus" ist nicht das einzige Argument, welches du für so ein merkwürdiges Konstrukt (const unique&) anführen kannst.
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]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

32

01.04.2015, 21:22

4) Raw-Pointer sind schon irgendwie hübscher als const-Referenzen auf Unique-Pointer.

Sie sind nicht nur hübscher. Wer Referenzen auf const unique_ptr herumreicht, der hat unique_ptr nicht verstanden. Smart Pointer sind kein Ersatz für Zeiger. Smart Pointer dienen dazu, den Besitz von dynamischen Objekten zu regeln. Wenn es dagegen darum geht, Objekte herumzureichen, verwendet man rohe Zeiger oder Referenzen.

4) Raw-Pointer sind schon irgendwie hübscher als const-Referenzen auf Unique-Pointer.

Klar sind sie hübscher, aber dafür hat man auch moderneren Code. Man benutzt heutzutage schließlich auch void bar(const std::vector<Foo>& foobar) statt void bar(Foo foobar[])

Imo ist die Variante mit dem Array zu bevorzugen, da sie für alle möglichen Arten von Arrays (inklusive std::vector) funktioniert, nicht nur für std::vector...

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (01.04.2015, 21:27)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

33

01.04.2015, 21:29

Nur funktioniert es in diesem Fall leider nicht, weil man auch die Länge des Arrays übergeben müsste ;) Zudem ist es eine Frage dessen, was man ausdrücken will. Übergibt man eine Referenz, die gespeichert werden darf und bei der Änderungen der Elemente darin nachvollzogen werden können vom Emfänger (er hat also immer Zugriff auf die aktuell darin enthaltenen Elemente, auch zu einem späteren Zeitpunkt) oder soll es nur um einen flüchtigen Blick auf einen aktuellen Zustand gehen?
Zudem ist eine Umstellung von z.B. std::vector auf std::list oder std::deque später wesentlich einfacher. Bei einem Raw-Array sieht das aber ganz anders aus. Da darf man zumeist einiges umbauen.
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]

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »BlueCobold« (01.04.2015, 21:35)


Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

34

01.04.2015, 22:20

4) Raw-Pointer sind schon irgendwie hübscher als const-Referenzen auf Unique-Pointer.

Klar sind sie hübscher, aber dafür hat man auch moderneren Code. Man benutzt heutzutage schließlich auch void bar(const std::vector<Foo>& foobar) statt void bar(Foo foobar[])

Imo ist die Variante mit dem Array zu bevorzugen, da sie für alle möglichen Arten von Arrays (inklusive std::vector) funktioniert, nicht nur für std::vector...


Wenn man verschiedene Datenstrukturen unterstützen will darf man wohl nur Iteratoren annehmen.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

35

01.04.2015, 23:58

Warum sollte man auf std::list oder std::deque umstellen wollen?
Die Container haben sich bei mir in der Praxis noch nie als vorteilhaft herausgestellt.

Ich würde meistens einen Zeiger und die Länge übergeben. Dann kann zwar leider noch nicht beliebige Iteratoren übergeben, aber eben alle Daten die kontinuierlich im Speicher vorliegen. Das schließt schonmal ein wenig mehr ein.

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

36

02.04.2015, 00:33

Eine Frage noch: Wenn ich jetzt folgendes z.B. mache:

C-/C++-Quelltext

1
2
3
4
int* i = new int;
double* d = i;

delete d;


Was passiert dann? Hat er hier auch einen Header wo steht wieviel reserviert wurde, oder verlässt er sich auf den Typ und versucht 8 Bytes freizugeben?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

37

02.04.2015, 00:34

Was passiert dann?

Das kompiliert nicht.

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

38

02.04.2015, 00:40

Und wenn Du es umcastest für die Zuweisung, funktioniert es, aber nur aus Versehen. int und double haben keinen Destruktor, deswegen geht das. Könnte höchstens irgendne Heap-Verifizierung triggern, wenn Du Glück hast und die Runtime es gut mit Dir meint.

Das Problem wird spannender bei sowas:

C-/C++-Quelltext

1
2
3
4
struct Bla { std::vector<int> v; }
int* i = new int;
auto bla = reinterpret_cast<Bla*> (i);
delete bla;


Dann wird der Destruktor von Bla aufgerufen, der automatisch erzeugt den Destruktor von Bla::v aufruft, der wahrscheinlich crasht, weil an der Stelle im Speicher ein int mit undefinierten Inhalt steht.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

39

02.04.2015, 06:44

Wenn man verschiedene Datenstrukturen unterstützen will darf man wohl nur Iteratoren annehmen.
Iteratoren sind aber eventuell gar nicht das, was der Empfänger braucht. Wenn er wahlfreien Zugriff benötigt, sieht es mit einem Iterator sehr schlecht aus. Ein RandomAccessIterator könnte wiederum gehen.

Warum sollte man auf std::list oder std::deque umstellen wollen?
Die Container haben sich bei mir in der Praxis noch nie als vorteilhaft herausgestellt.
Im Gegensatz zu std::vector wird bei einer List oder Deque garantiert, dass die bereits darin enthaltenen Elemente ihre Adresse immer behalten, egal ob Du Elemente entfernst oder hinzufügst. Das kann schon manchmal sehr wichtig sein. Außerdem wissen wir ja, dass Lösch- oder Einfüge-Operationen auf einem Vektor potentiell sehr teuer sein können. Muss der Empfänger z.B. plötzlich immer vorn irgendwas anfügen statt wie bisher hinten... nun ja. Es kann durchaus vorkommen, dass sich das ändert.
Ein Array hat wie wir wissen ja außerdem noch ganz andere Probleme:
* Man muss die Größe mitschleifen
* Man muss die Größe *korrekt* übergeben. Das ist ein size_t und kein int. Konvertierung von size_t in irgendwas anderes? for (auto max = length; max > 0; --max)? Böses Aua, weil Endlosschleife.
* Man muss die Größe steht's selbst prüfen, was potentiell fehleranfällig (im schlimmsten Fall für Exploits durch Bufferoverflows) ist
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]

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

40

02.04.2015, 11:21

Das Geheimnis bei Vektoren ist es entweder mit Indices zu arbeiten, oder aber wenn unvermeidlich mit std::vector<std::unique_ptr<T>>. Das mit dem Einfügen und Entfernen stimmt zwar, allerdings ist es sehr selten notwendig wirklich vorne Elemente einzufügen oder zu löschen. Häufig spielt entweder die Reihenfolge keine Rolle oder man kann einfach die Reihenfolge genau spiegeln und so auch die teueren Operationen vermeiden. Außerdem ist bei der std::list das Einfügen und Entfernen durch Allokationen bis zu etwa Tausend Elementen auch nicht schneller. Über eine std::list lässt sich nur langsam iterieren. Meistens iteriert man aber viel mehr als man Elemente vorne hinzufügt/entfernt. Alles in allem ist die std::list einfach eine sehr selten wirklich vorteilhafte Datenstruktur. Ich kann mich nicht an eine Situation bei mir erinnern, in der std::list wirklich vorteilhaft gewesen wäre.

Mit den Punkten hast du sicher recht, das es ein klein wenig mehr Aufwand darstellt.
Nichtsdestotrotz überwiegt meiner Meinung nach der Vorteil, dass man nicht an den std::vector gebunden ist.
Ab und zu habe ich doch C Arrays rumliegen. Sei es wegen einer C Biblitiothek oder wegen den etwas kleineren Speicheroverhead.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Spiele Programmierer« (02.04.2015, 11:26)


Werbeanzeige