2d array (vector*vector) schnell initialisieren
-
Ich habe ein Feld
vector<vector<uint8>> Feld(size_y, vector<uint8>size_x);
zur Laufzeit wird erst festgelegt was size_x und size_y ist.
Dann wird damit ein Rezize ausgeführt.In einer loop muss das Feld aber immer wieder mit Nullen befüllt werden, daher soll das ganze möglichst schnell sein.
Ich denke memset ist die einzige Möglichkeit, meine 2 for-Schleifen abzulösen, oder? Das ganze läuft in VC++ 2010 Express.
-
Da du nicht der einzige bist, der in letzter Zeit eine falsche Vorstellung von 2D-Arrays hat:
http://www.c-plusplus.net/forum/p2422591#2422591Wenn du einer der dort vorgeschlagene Möglichkeiten benutzt (die letzte der drei scheint die passende zu sein), beschränkt sich das Nullen auf ein einzelnes fill. Und die ganze Struktur ist bei jeder Art von Zugriff wesentlich schneller als vector<vector>. Wieso muss das Feld eigentlich immer wieder neu mit Nullen überschrieben werden? Was hast du vor?
-
SeppJ schrieb:
Da du nicht der einzige bist, der in letzter Zeit eine falsche Vorstellung von 2D-Arrays hat:
http://www.c-plusplus.net/forum/p2422591#2422591 ...Du schreibst in dem mittlerweile geschlossenen Thema des Links
"Die Flexibilität, die man bei vector<vector> hat, geht auf Kosten der Laufzeit im Vergleich zu echten 2D-Arrays."Das gilt beim GCC nicht, wenn das Programm mit -O2 oder -O3 übersetzt wird.
Ein 2D-Array, einmal mit new [zeilen * spalten] und einmal mit vector<double>(zeilen * spalten) implementiert, liefert für eine Multiplikation zweier 1000 x 1000 Matrizen
in Sekunden:new vector keine Opt. 10,3 18,3 -O2 1,54 1,54 -O3 1,63 1,54Dies nur als Ergänzung. Der geringfügig erhöhte Wert 1,63 ist reproduzierbar.
-
sorry, missverständnis. Hatte
vector<vector>>überlesen
-
Warum kann man eigentlich den
operator[]nicht mit mehreren Argumenten überladen, so wie denoperator()? Sollte ja aus Compiler-Sicht kein Problem sein und dann könnte man 2D bzw. n-Dimensionale Container "schöner" addresieren - zumindest würde sich ein solcher Zugriff deutlich(er) von einem Funktionsaufruf abgrenzen und wäre konsistenter zu 1-Dimensionalen Containern wie z.B.std::vector:matrix<int> A(3, 3); // Erstellen A[0, 1] = 5; // Setzen std::cout << A[0, 1]; // LesenFände ich auch wesentlich besser besser als die
A[i][j]Variante, weil aus der geht ja wiederum nicht hervor dass es sich um ein "Matrix-ähnliches" Gebilde handelt...Gibt es einen speziellen Grund dafür dass das nicht erlaubt ist, oder ist das eventuell sogar schon geplant?
-
happystudent schrieb:
Warum kann man eigentlich den
operator[]nicht mit mehreren Argumenten überladen, so wie denoperator()?Weil der eingebaute [] nur ein Argument hat. Ein , darin wird als Kommaoperator interpretiert.
-
Bashar schrieb:
happystudent schrieb:
Warum kann man eigentlich den
operator[]nicht mit mehreren Argumenten überladen, so wie denoperator()?Weil der eingebaute [] nur ein Argument hat. Ein , darin wird als Kommaoperator interpretiert.
Aber es wäre afaik kein Problem, dem operator[] beliebig viele Argumente zu geben.
int operator[](int x, int y);Das entspricht dann:
arr[x][y]
-
Achso, du willst a[x][y] schreiben und das soll a.operator[](x,y) bedeuten? Und wie soll der Compiler das von a.operator[](x).operator[](y) unterscheiden?
BTW macht "afaik" bei Hypothesen nicht so viel Sinn

-
Bashar schrieb:
Achso, du willst a[x][y] schreiben und das soll a.operator[](x,y) bedeuten?
Jupp.
Und wie soll der Compiler das von a.operator[](x).operator[](y) unterscheiden?
Gar nicht. Das ist dann ambig, oder es wird immer der mit den meisten Argumenten genommen.
-
-
Bashar schrieb:
Ich finds aber sprachphilosophisch hässlich, Ausdrücke zu haben, die eigentlich keine sind.
Ja, das stört mich auch.
Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
Alles nicht das Wahre.
-
Nathan schrieb:
Aber es wäre afaik kein Problem, dem operator[] beliebig viele Argumente zu geben.
int operator[](int x, int y);Das entspricht dann:
arr[x][y]Naja, das fände ich jetzt schlecht um ehrlich zu sein. Erstens wegen mehrdeutigkeit und zweitens würde man dann ja wieder nicht sehen dass es sich (explizit) um eine "viereckige" 2-dimensionale Datenstruktur handelt. Schließlich lässt sich
vector<vector<T>>genauso indizieren, stellt aber etwas völlig anderes dar.Wenn schon fände ich sowas gut:
struct matrix { matrix(int rows, int cols) { /* Implementierung */ } int &operator[](int row, int col) { /* Implementierung */ } }; // Und dann so benutzen: int main() { matrix mat(3, 3); mat[0, 0] = 1; mat[1, 0] = 2; mat[2, 0] = 3; // etc. }Fände ich cool

Dann würde man schön den Unterschied sehen und es wäre konsistent zu 1D Containern.
-
Wie gesagt, das kollidiert mit der bestehenden Syntax.
-
Bashar schrieb:
Wie gesagt, das kollidiert mit der bestehenden Syntax.
Ja dieser blöde Komma-Operator

Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?Könnte man ja vielleicht so machen dass man wie beim
operator()auch extra Klammern angeben muss wenn man den Komma-Operator da verwenden will. Also so:mat(i, j); // operator()(int, int) mat((i, j)); // operator()(int) mat[i, j]; // operator[](int, int) mat[(i, j)] // operator[](int)Wäre auch irgendwie logischer. Die Frage wäre dann vermutlich wieviel alter Code durch so eine Umstellung kaputt gehen würde... Denke aber die wenigsten setzen einen Komma-Operator so innerhalb von eckigen Klammern ein

-
Nathan schrieb:
arr.at(y,x) übersetzt.Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
Alles nicht das Wahre.
-
happystudent schrieb:
Ja dieser blöde Komma-Operator

Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?Arcoth hatte neulich eine nette Verwendung mit SFINAE, afair sizeof(foo,0).
Könnte man ja vielleicht so machen dass man … extra Klammern angeben muss wenn man den Komma-Operator da verwenden will. Also so:
mat(i, j); // operator()(int, int) mat((i, j)); // operator()(int) mat[i, j]; // operator[](int, int) mat[(i, j)] // operator[](int)[/quote]
Compilerbaue könnten eine Warnung einbauen, wenn man um einen Kommaoperatorausdruck keine Klammern macht.
-
volkard schrieb:
Nathan schrieb:
arr.at(y,x) übersetzt.Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
Alles nicht das Wahre.Nein, &arr[y] geht nicht wie bei nativen Arrays.
volkard schrieb:
happystudent schrieb:
Ja dieser blöde Komma-Operator

Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?Arcoth hatte neulich eine nette Verwendung mit SFINAE, afair sizeof(foo,0).
Nicht nur Arcoth, sizeof(foo, 0) oder decltype(foo, 0) kann man ständig gebrauchen.
Außerdem gibts da noch das for-each-parameter-pack:char dummy[] = {(func(bla), '\0')..., '\0'};
-
char dummy[] = {(func(bla), '\0')..., '\0'};Das ist nicht so optimal.
std::initialier_list<int>{ (func(bla),0)... };Oder mit
struct evaluate{ template <typename... A> constexpr evaluate(A&&...) {} }; evaluate{ func(bla)... };
-
Nathan schrieb:
Nein, &arr[y] geht nicht wie bei nativen Arrays.
Ach, Du willst wirklich auf einem 2D-Array &arr[y] machen. Ok, sehe den Bedarf nicht. Zu viele Implementierungen könnten auch keine sinnvolle getRow(y) anbieten.
&arr[y] ist nur ein Hack, den man nehmen kann, wenn man das Speicherlayout zufällig genau kennt und es sich nie wieder ändern wird. &arr[0][y] dürfte gehen.
-
Arcoth schrieb:
char dummy[] = {(func(bla), '\0')..., '\0'};Das ist nicht so optimal.
std::initialier_list<int>{ (func(bla),0)... };Oder mit
struct evaluate{ template <typename... A> constexpr evaluate(A&&...) {} }; evaluate{ func(bla)... };Und wenn ich es sequenced haben will?
volkard schrieb:
Nathan schrieb:
Nein, &arr[y] geht nicht wie bei nativen Arrays.
Ach, Du willst wirklich auf einem 2D-Array &arr[y] machen. Ok, sehe den Bedarf nicht. Zu viele Implementierungen könnten auch keine sinnvolle getRow(y) anbieten.
&arr[y] ist nur ein Hack, den man nehmen kann, wenn man das Speicherlayout zufällig genau kennt und es sich nie wieder ändern wird. &arr[0][y] dürfte gehen.Nee, brauchen würd ich das auch nicht.
Aber das ist halt der Nachteil, dass arr[x][y], eine expression ist, anstatt wie sonst auch zwei verschiedene.