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

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

21

10.08.2012, 16:55

Jetzt verstehe ich, dir ging es immer nur darum, dass es rein theoretisch möglich ist die Länge zu verändern und man es darum nicht verwenden soll.

Mehr oder weniger, ja. Mir ging (und geht) es darum, dass ein std::vector<std::vector<T>> semantisch etwas ganz anderes ist als ein rechteckiges Array. Und da wir aber ein rechteckiges Array haben wollen, ist std::vector<std::vector<T>> hier eben keine gute Wahl.

Wenn der Threadersteller überhaupt nur ein Array statischer Größe haben will, wäre ein stinknormales sf::Color[40][11] übrigens wohl die beste Lösung.
Bis auf dass er sich selbst die grösser merken muss (schlechtes Design, Eigenschaften eines 'Objekts' werden ausserhalb gelagert) und auch viel mehr aufpassen muss mit den Indizes.

Nicht unbedingt, denn da es sich um ein Array statischer Größer handelt, gehört die Größe natürlich zum Typ. Aber gut, noch besser wäre dann also ein std::array. Wieso er mit den Indices "viel mehr" aufpassen muss, ist mir allerdings nicht ganz klar.

Naja auch nicht ganz richtig vector Mechanismen werden sehr wohl auf dem Stack gespeichert, nur die Daten halt nicht, doch ich denke es macht hier nun wirklich bald mal keinen Sinn mehr zu diskutieren was nun schneller ist, denn am Ende wird das Ganze dann doch vom OS entschieden und wer weiss wie dieses sich in allen Fällen und unter allen möglichen Umständen verhält. ;)

Korrekt, da hab ich mich ursprünglich falsch ausgedrückt, daher hab ich's dann noch editiert. Rein prinzipiell wird eine Stack Allocation immer wesentlich schneller sein als eine Heap Allocation, da erstere einfach nur ein Pointerinkrement ist. Im Fall einer lokalen Stack Allocation statischer Größe, ist der Overhead in der Regel wohl tatsächlich sogar Null, da das Array im, beim Function Call aufgebauten, Stackframe liegt. Natürlich hängt es genaugenommen von der jeweiligen Plattform ab. Genaugenommen sagt der Standard eigentlich ja überhaupt nichts von einem Stack oder einem Heap oder sonstwas. Trotzdem sind das Dinge, von denen man mehr oder weniger ausgehen kann. Hardware, wo das tatsächlich anders läuft, gibt es, ist für uns hier aber wohl uninteressant. Ein Beispiel wären GPUs. Das sind dann aber sowieso Architekturen mit fundamental verschiedener Performancecharakteristik. Was dynamische Speicherallokationen auf GPUs für einen Overhead haben, willst du gar nicht wissen (State of the Art sind Größenordnungen im Bereich von 10^4 bis 10^7 Cycles).

Interessante Anmerkung noch: Wenn der Speicher eines vectors bei der Initialisierung alles auf einmal alloziert wird, so wird der Speicherbereich in den meisten Fällen ebenfalls kontinuierlich sein. Klar dies ist nicht garantiert aber es zeigt halt, wieso es in den meisten Fällen nicht sehr tragisch ist 2D vectoren zu verwenden, auch wenn sie halt die Möglichkeit bieten sich selbst zu vergrössern/verkleinern und dies nicht direkt gewollt ist.

Die Theorie funktioniert nur, solange man Dinge wie interne und externe Fragmentierung ignoriert. In der Praxis werden wir es hier im Idealfall aber wohl zumindest mit interner Fragmentierung (Größe des Arrays muss irgendwo gespeichert werden, Alignment, Allocator Granularity etc.) zu tun haben. Unabhängig davon, kommt es darauf an, wie genau man mit dem vector umgeht. Selbst ein simples push_back() macht schon wieder alles zunichte. Auch wenn die Speicherblöcke der einzelnen vectoren also tatsächlich nacheinander allokiert werden, bedeutet das also noch lange nicht, dass die Daten auch zusammenhängend sind. Natürlich könnte man evtl. einen eigenen speziellen Allocator schreiben, um das zu erreichen...

Wieso mir der zusammenhängende Speicherbereich wichtig ist, hat in erster Linie ebenfalls wieder nicht unbedingt mit der Performance zu tun. Es ist einfach eine sehr angenehme Eigenschaft und sehr oft einfach notwendig. Z.B. wenn ich meine multidimensionalen Daten an irgendeine API übergeben will, z.B. Bilddaten oder Matritzen an Direct3D/OpenGL...

Hier ein kleines Beispiel, der erste Part zeigt was man alles komische mit der Array Definition im Standard anstellen kann und zeigt gleichzeitig, dass der Speicher fortlaufend ist und der zweite Teil gibt die Adressen eines vectors aus, womit man sieht, dass dieser Speicher ebenfalls kontinuerlich alloziert wird (aber nicht garantiert ist!). :)

Das sieht nur auf den ersten Blick so aus. Wenn man genauer hinschaut, fällt auf, dass die Speicherblöcke zwar in der Tat hintereinander alloziert wurden, die Daten aber nicht zusammenhängend sein können, da die Differenz zwischen den Adressen 18 Byte beträgt und 18/8 keine natürliche Zahl ist. Wir haben also eine interne Fragmentierung von 2 Byte pro Block. Wenn du mit dem verschachtelten vector das gleiche Spielchen anstellst wie davor mit dem Array, wirst du hochinteressante Ergebnisse bekommen... ;)

Btw: Statt dem reinterpret_cast besser &a[0][0][0] machen, da das Ergebnis des reinterpret_cast in dem Fall unspecified ist.

Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von »dot« (10.08.2012, 17:22)


22

10.08.2012, 18:56

Chill down. ;)
Ich machs jetzt so, dass ich als Membervariable ein 2D-Array an Instanzen erzeuge und diese dann nicht mehr per Konstruktor, sondern Init-Methode mit Werten fülle.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

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

  • Private Nachricht senden

23

10.08.2012, 19:12

Ich hab noch einen improvisierten 2d Vector aus einem alten Projekt. Er ist zwar nicht perfekt oder fertig, wird aber für deine zwecke völlig ausreichend sein.
http://pastebin.com/uHU0Gw3w
Einfach iin einen Header kopieren und benutzen.
"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?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

24

10.08.2012, 22:11

Chill down. ;)

Tut mir leid, wenn du den Eindruck hattest, dass ich angespannt wär. Ich führ solche Grundsatzdiskussionen gern, weil ich immer was dabei lernen kann. Das ganze war eigentlich nicht so direkt an dich gerichtet... ;)

25

11.08.2012, 08:40

@NachoMan Danke, aber ich benutze lieber ein normales 2D-Array, da ich mir die Funktionen dafür dann lieber selber schreibe, um mehr zu lernen.
Tut mir leid, wenn du den Eindruck hattest, dass ich angespannt wär. Ich führ solche Grundsatzdiskussionen gern, weil ich immer was dabei lernen kann. Das ganze war eigentlich nicht so direkt an dich gerichtet... ;)
Nein, ich meinte nicht explizit dich. Außerdem war das auch ein bisschen ironisch gemeint. Also ich führe selbst auch gerne solche Diskussionen in anderen Bereichen. ;)
Fand es nur etwas lustig, wie erst 2 Tage keiner mehr was postet und es dann auf einmal 2 Seiten mehr sind.
Verstehen kann ich natürlich nicht alles was ihr dort gegenseitig zitiert und kommentiert, aber ich bin froh euch dazu angeregt zu haben, dass ihr es macht.
Denn ich glaube so lernen sogar die schon recht professionellen Programmierer hier im Forum was dazu. Niemand weiß alles. :)

eXpl0it3r

Treue Seele

  • »eXpl0it3r« ist der Autor dieses Themas

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

26

11.08.2012, 15:54

Nicht unbedingt, denn da es sich um ein Array statischer Größer handelt, gehört die Größe natürlich zum Typ. Aber gut, noch besser wäre dann also ein std::array.
Interessant dieses extent template struct, aber ist wohl eher eine Symptom Bekämpfung wie eine Lösung, ist aber natürlich am richtigen Ort durch aus notwendig und sicherlich besser als das C idiom, welches ja nicht type-safe ist.
Wieso er mit den Indices "viel mehr" aufpassen muss, ist mir allerdings nicht ganz klar.
Naja gut alle Container haben das Problem eines underflow oder overflow, von daher muss man überall gleich aufpassen. Mit std::vector<T> hätte man natürlich noch die Möglichkeit .at() zu verwenden, jedoch hat das natürlich auch wieder seine Nachteile.
Wieso mir der zusammenhängende Speicherbereich wichtig ist, hat in erster Linie ebenfalls wieder nicht unbedingt mit der Performance zu tun. Es ist einfach eine sehr angenehme Eigenschaft und sehr oft einfach notwendig. Z.B. wenn ich meine multidimensionalen Daten an irgendeine API übergeben will, z.B. Bilddaten oder Matritzen an Direct3D/OpenGL...
Das ist mal wieder etwas légere formuliert, zumindest ist es für mich nicht wichtig wie 'angenehm' Speicher ausgelegt wird, sondern ob es technisch gesehn Sinn macht, wie du eben noch angefügt hast, dass verschiedene APIs es so verlangen. ;)
Das sieht nur auf den ersten Blick so aus. Wenn man genauer hinschaut, fällt auf, dass die Speicherblöcke zwar in der Tat hintereinander alloziert wurden, die Daten aber nicht zusammenhängend sein können, da die Differenz zwischen den Adressen 18 Byte beträgt und 18/8 keine natürliche Zahl ist. Wir haben also eine interne Fragmentierung von 2 Byte pro Block. Wenn du mit dem verschachtelten vector das gleiche Spielchen anstellst wie davor mit dem Array, wirst du hochinteressante Ergebnisse bekommen... ;)
Ja das ist klar und bei der kleinsten Änderung der vectoren kann sich alles verschieben.
Chill down.
Tut mir leid, wenn du den Eindruck hattest, dass ich angespannt wär. Ich führ solche Grundsatzdiskussionen gern, weil ich immer was dabei lernen kann. Das ganze war eigentlich nicht so direkt an dich gerichtet...
Ja war für mich zumindest sehr lehrreich.
War am Anfang halt ein bisschen hitzig, da die Statements nicht sehr klar waren und man noch nicht wusste auf welchem Level man diskutieren kann (und dann ab und zu wieder Trolls kamen...). :)
Ich hab noch einen improvisierten 2d Vector aus einem alten Projekt. Er ist zwar nicht perfekt oder fertig, wird aber für deine zwecke völlig ausreichend sein.
http://pastebin.com/uHU0Gw3w
Einfach iin einen Header kopieren und benutzen.
Naja ich würde jetzt dies Klasse auch nicht direkt empfehlen, oder noch ein paar Dinge ändern. Z.B. ist die resize() Funktion ziemlich problematisch, weil du einfach das Array vergrösserts, aber die Elemente selbst nicht umher schiebst, d.h. wenn du jetzt ein 4x4 Feld hast und es auf 16x16 erweiterst, dann werden die 4x4 Felder plötzlich alle auf einer Zeile stehen. Gut vielleicht ist das ein gewünschter Effekt, aber meinstens wohl eher nicht. Ausserdem, wieso initialisierst du den vector nicht direkt in der Initialisierungsliste mit der passenden Grösse, nur um dann später resize() aufzurufen?
Aber könnte durchaus nützlich sein für Anfänger um eine Idee davon zu erhalten. :)
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

27

11.08.2012, 16:02

In erster Linie ging es um die Klärung der Frage des TE. Eure Diskussion ist eig. ziemlich ausgeufert (jedenfalls denke ich mal wusste der TE oft nicht worum es gerade geht) und insofern hat idontknow keineswegs destruktive Beitrage verfasst -> somit auch kein "getrolle" betrieben.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

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

  • Private Nachricht senden

28

11.08.2012, 16:08

Was ist an "improvisiert", "alt", "nicht perfekt", "nicht fertig" und "reicht für seine Zwecke" so schwer zu verstehen?^^

Die Resizemethode ist eigentlich auch nicht dazu gedacht das Feld nachträglich zu vergrößern ohne selbst die Objekte darin zu verschieben. Ich kann ja nicht wissen ob das Feld nach links, rechts, oben, unten oder allen Richtungen vergrößert wird. Daher überlasse ich es den Nutzer ein altes 2D Array in ein neues, größeres zu kopieren. Ich habe die Methode nur erstellt, weil man möglichst einen Standardkostruktor ohne Parameter zur Verfügung stellen sollte und es ohne diese Methode keine Möglichkeit gäbe die größe festzulegen.

@Nathax: Du kannst es dir ja mal anschauen und versuchen zu verstehen. ;)
"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?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »NachoMan« (11.08.2012, 17:58)


eXpl0it3r

Treue Seele

  • »eXpl0it3r« ist der Autor dieses Themas

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

29

11.08.2012, 17:42

In erster Linie ging es um die Klärung der Frage des TE. Eure Diskussion ist eig. ziemlich ausgeufert (jedenfalls denke ich mal wusste der TE oft nicht worum es gerade geht) und insofern hat idontknow keineswegs destruktive Beitrage verfasst -> somit auch kein "getrolle" betrieben.
Zum Zeitpunkt seines Posts war die Diskussion noch längst nicht fertig und seine plumpige Antwort à la "Eure Diskussion ist schwachsinn und ich weiss alles besser: std::array" würde ich schon als getrolle bezeichnen (auch die zwei Edits zeigen, dass er nur schnell etwas hingeschrieben hat anstatt sich die Diskussion durchgelesen hat). Hätte er versucht sich in die Diskussion einzuklinken und mit std::array eine gute Alternative vorgeschlagen, hätte das Ganze etwas anderst ausgesehen. ;)

Was ist an "improvisiert", "alt", "nicht perfekt", "nicht fertig" und "reicht für seine Zwecke" so schwer zu verstehen?^^
Das hab ich schon verstanden, ich dachte nur ich weise auf die groberen Mägel hin, anstatt nur zu sagen, dass es nicht perfekt. ;)
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

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

  • Private Nachricht senden

30

11.08.2012, 17:51

Was ist an "improvisiert", "alt", "nicht perfekt", "nicht fertig" und "reicht für seine Zwecke" so schwer zu verstehen?^^
Das hab ich schon verstanden, ich dachte nur ich weise auf die groberen Mägel hin, anstatt nur zu sagen, dass es nicht perfekt. ;)

Ich würde mich über jeden Lösungsvorschlag für diesen "groben Mangel" freuen. :thumbsup:
"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?

Werbeanzeige