Stack Overflow vermeiden
-
Schön dass es offenbar eine Lösung gibt, aber sorry, ich verstehe nur noch Bahnhof. Wie muss ich das jetzt anwenden, um mein 6-dimensionales Array zu erhalten?
-
Am einfachsten so, wie es hustbaer gezeigt hat.
Beachte, dass auto_ptr ein Smart Pointer ist und den Speicher, den du mit new angelegt hast wieder frei gibt.
-
Ganz direkt geht Folgendes:
int (*h)[2][4][3][21][730] = new int[2][2][4][3][21][730]; // ... delete[] h;
Aber ich bin wirklich der Ansicht, dass Boost.Multi-Array die einfachste Möglichkeit ist - hauptsächlich aus Gründen der Exception-Sicherheit. Einen Block Speicher dieser Größe willst du wirklich nicht verlieren.
-
Ok, ich fasse mal zusammen. Man macht es entweder mit boost, was ich aber nicht so gerne machen möchte, da dann alle, die an dem Projekt mitarbeiten, das erst mal installieren müssen. Oder man benutzt eine der folgenden drei Möglichkeiten:
#include <vector>; #include <iostream>; using namespace std; int main(char* argv[]) { // Möglichkeit 1 mit vector vector<vector<vector<vector<vector<vector<int> > > > > > h1(2, vector<vector<vector<vector<vector<int> > > > >(2, vector<vector<vector<vector<int> > > >(4, vector<vector<vector<int> > >(3, vector<vector<int> >(21, vector<int>(730)))))); h1[1][1][1][1][1][1] = 42; cout << h1[1][1][1][1][1][1] << endl; // Möglichkeit 2 mit struct struct InfRegAgeHeaInfDay { int data[2][2][4][3][21][730]; }; auto_ptr<InfRegAgeHeaInfDay> h2(new InfRegAgeHeaInfDay()); (*h2).data[1][1][1][1][1][1] = 43; cout << (*h2).data[1][1][1][1][1][1] << endl; // Möglichkeit 3 mit pointer int (*h3)[2][4][3][21][730] = new int[2][2][4][3][21][730]; h3[1][1][1][1][1][1] = 44; cout << h3[1][1][1][1][1][1] << endl; delete[] h3; system("PAUSE"); }
Davon ist die erste wohl die schlechteste, da für jedes Array ein riesen Schreibaufwand entsteht und Compileroptimierungen bei der Indexberechnung verloren gehen.
Die zweite hat eine etwas unübersichtliche Syntax und ich sehe keinen konkreten Vorteil zur Möglichkeit 3.
Ich werde also trotz der Exception-Unsicherheit (ist das tatsächlich ein Problem?) die dritte verwenden, da ich dann fast nichts am bestehenden Code ändern muss.
-
Wie wäre es damit:
struct MyBigArray { int (*data)[2][4][3][21][730]; MyBigArray() { data = new int[2][2][4][3][21][730]; } ~MyBigArray() { delete[] data; } int (*operator [])(std::size_t idx)[2][4][3][21][730] { return (*data)[idx]; } }; ... MyBigArray a; a[1][1][1][1][1][1] = 45;
(ungetestet, möglicherweise mit Schreibfehlern)
-
Naja, der Punkt ist, dass du darauf achten musst, dass der Speicher auch aufgeräumt wird, wenn eine Exception geworfen wird - etwa führt
int (*h3)[2][4][3][21][730] = new int[2][2][4][3][21][730]; throw std::logic_error("Ups, Fehler!"); delete[] h3;
zu einem Speicherleck. boost::multi_array löst das Problem per RAII, wie es in C++ zur Ressourcenverwaltung üblich ist.
Man kann das relativ einfach ranpatchen:
template<typename array_t> class array_memory_guard { public: array_memory_guard(array_t *data): data_(data) { } ~array_memory_guard() { delete[] data_; } private: array_t *data_; }; // ... { int (*h3)[2][4][3][21][730] = new int[2][2][4][3][21][730]; array_memory_guard<int[2][4][3][21][730]> memguard(h); throw std::logic_error("Ups, Fehler!"); } // Speicher wird hier aufgeräumt
..worin der Destruktor des "Speicherwächters" beim Verlassen des Scopes auch durch eine Exception den Speicher aufräumt. Wenn du Boost wirklich nicht benutzen willst, ist das eine Option, aber die Eigenschaftsverhältnisse sind hier natürlich deutlich weniger sauber.
-
// Möglichkeit 2.5 mit struct und pointer struct InfRegAgeHeaInfDay { int data[2][2][4][3][21][730]; }; auto_ptr<InfRegAgeHeaInfDay> guard(new InfRegAgeHeaInfDay()); int (*const h25)[2][4][3][21][730] = guard->data; h25[1][1][1][1][1][1] = 44; cout << h25[1][1][1][1][1][1] << endl; // freigeben tut der guard, wir müssen nur drauf achten h25 nimmer zu verwenden nachdem guard gestorben ist
EDIT
@seldon: dein Guard sollte noch noncopyable sein
-
Wunderbar, dann nehm ich 2.5
Danke für all die Antworten.
-
Hustbaers Ansatz gefällt mir für diesen Anwendungsfall. Bestechend einfach, und die ganze Arbeit wird von Standardmechanismen übernommen - wenig Gefahr, etwas zu übersehen (wie die Kopierbarkeit des Speicherwächters) und wenig Arbeit. Die Rückgabe aus Funktionen ist damit auch einfach möglich.
ipsecs Ansatz ist natürlich sehr luxuriös, wenn man sich die Arbeit macht, das Interface zu vervollständigen. Je öfter derartiger Code öfter im Programm benutzt wird, desto sinnvoller wird diese Variante - das bewegt sich vom Grundgedanken her ja schon in die Richtung des genannten Multi-Arrays.
Ich ziehe also meinen Vorschlag zurück. Bessere sind gemacht worden.
-
Leider funktioniert es noch nicht ganz. Das Programm läuft zwar durch die komplette Simulationsschleife durch, aber wenn es terminiert kommen folgende Fehlermeldungen:
www.phynet.de/private/snOOfy/fehler.png
Es öffnet sich die Datei free.c und der Zeiger (Haltepunkt) steht vor der Zeile
retval = HeapFree(_crtheap, 0, pBlock);Muss ich mit diesen guard Dingern noch irgendwas machen bevor sich das Programm beendet?
-
snOOfy schrieb:
retval = HeapFree(_crtheap, 0, pBlock);
Deswegen multi_array oder vector<array<...
Die können Indexgrenzenüberprüfungen machen.
Hast irgendwo hinter das Ende des Arrays geschrieben.
-
Oha... deswegen mag ich Java. Da hätte das eine ArrayIndexOutOfBounds Exception gegeben und einen Hinweis auf die Zeilennummer, in der es passiert ist. Hier such ich jetzt wieder Ewigkeiten bis ich das finde^^
-
int bei(int i,int r,int a,int s,int z,int d){ assert(0<=i && i<2); assert(0<=r && r<2); ... return ((((((d)*730+z)*21+s)*3+a)*4+r)*2+i) } ... vector<int> v(2*2*4*3*21*730); v[bei(1,1,2,1,3,123)]=17;
-
snOOfy schrieb:
Oha... deswegen mag ich Java. Da hätte das eine ArrayIndexOutOfBounds Exception gegeben und einen Hinweis auf die Zeilennummer, in der es passiert ist. Hier such ich jetzt wieder Ewigkeiten bis ich das finde^^
Deswegen hasse ich Java, weil sowohl fachliche als auch programmtechnische Fehler, Ausnahme und Probleme nur geschießen werden und komplex System extrem unwartbar macht. - "des anderen leid ist des anderen freunde"
-
snOOfy schrieb:
Oha... deswegen mag ich Java. Da hätte das eine ArrayIndexOutOfBounds Exception gegeben und einen Hinweis auf die Zeilennummer, in der es passiert ist. Hier such ich jetzt wieder Ewigkeiten bis ich das finde^^
naja in sauber programmiertem c++ code mit logfile weisst du nicht nur die zeile sondern auch den zeitpunkt usw. usw. usw. ...
-
Ich weiß ich habe damit angefangen, aber meine Äußerung sollte hauptsächlich meinen Frust verdeutlichen und keine Java vs. C++ Diskussion lostreten
Ja, ich bin dabei eine LOG zu erstellen, werd Bescheid geben wenn das Problem gelöst ist.
// Edit: Ist gelöst
-
Eigentlich sollte bei der Variante von hustbaer dein Compiler meckern, da lokale Typen nicht als Templateargumente verwendet werden können.
-
@KasF:
Richtig.Ich bin davon ausgegangen dass er nur im Beispiel eine lokale Klasse verwendet (zwecks weniger tippen), nicht aber im eigentlichen Programm.
-
Ich habe aber tatsächlich alles genau wie im Beispiel gemacht, also einfach
// humans[immunity][region][age][health][infections survived][date] struct ImmRegAgeHeaInfDay {int data[2][2][4][3][21][simulatedDays]; }; auto_ptr<ImmRegAgeHeaInfDay> guardH(new ImmRegAgeHeaInfDay()); int (*const h)[2][4][3][21][simulatedDays] = guardH->data;
in der main() Funktion. Sollte ich da dran was ändern?
-
simulatedDays ist hoffendlich eine constante...
denn wenn du 6 dimensionale arrays dynamisch erstellen willst, dann haste was zu tun und ich wünsch dir viel spass