Speicher fuer dim x dim Matrix anfordern
-
int main() { unsigned x; cin >> x; double** matrix = new double*[x]; unsigned y; cin >> y; for(unsigned i=0; i!=x; ++i) { matrix[i] = new double[y]; } for(unsigned i=0; i!=x; ++i) { delete matrix[i]; } delete matrix; }
-
Warum nicht x*y an einem Stück?
-
Meinst du sowas:
int groesse = 42; int *pArray; pArray = new int[groesse]; delete [] pArray;Und gespickt habe ich da nicht. Das Problem ist das new und delet bei uns auch nur in ca. 10 Zeilen Code erklärt wird.
-
Entsprechenden Include-Pfad für Eigen vorausgesetzt:
#include <iostream> #include <Eigen/Dense> using std::cout; using Eigen::MatrixXd; int main() { MatrixXd mat = MatrixXd::Identity(9,9)*23; cout << mat(0,0) << '\n'; cout << mat(1,0) << '\n'; }(ungetestet)
Man kann sich aber natürlich auch das Leben schwer machen und dieses Rad schlecht nachbauen.

-
Unnötige, schlechte Eigennachbauten von Standardklassen? Ich höre den Ruf und eile herbei!
template<typename ElementType> class MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy { private: ElementType *data; unsigned long size; public: MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy(unsigned long size): data(new ElementType[size]), size(size) { } ~MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy() { delete[] data; } MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy (const MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy& other): data(new ElementType[other.size]), size(other.size) { // My unnecessary, bad and tedious clone of std::copy // which is not even the correct way of doing this // (should get uninitialized memory and use something // like uninitalized_copy) for (unsigned long i = 0; i < size; ++i) data[i] = other.data[i]; } MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy& operator= (MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy other) { // My unnecessary, bad and tedious clone of std::swap ElementType* temp = data; data = other.data; other.data = temp; unsigned long temp2 = size; size = other.size; other.size = temp2; return *this; } ElementType& operator[](unsigned long i) { return data[i]; } const ElementType& operator[] (unsigned long i) const { return data[i]; } }; template <typename ElementType> class Array2D { private: MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy<ElementType> data; unsigned long size_x; public: Array2D(unsigned long size_x, unsigned long size_y) : data(size_x * size_y), size_x(size_x) {} ElementType& operator()(unsigned long x, unsigned long y) { return data[x + y * size_x]; } const ElementType& operator() (unsigned long x, unsigned long y) const { return data[x + y * size_x]; } }; #include <iostream> int main() { using std::cout; Array2D<int> foo(4,5); int i = 0; for (int x = 0; x < 4; ++x) for (int y = 0; y < 5; ++y) foo(x,y) = ++i; // Ein bisschen RAII testen: Array2D<int> bar(foo); Array2D<int> foobar(7,3); foobar = bar; for (int x = 0; x < 4; ++x) { for (int y = 0; y < 5; ++y) cout << foobar(x,y) << " "; cout << '\n'; } }cout habe ich jetzt mal nicht nachgebaut, weil das irgendwann auf systemabhängiger Ebene geendet hätte.
-
Du hast
operator newnicht redefiniert.
Klares Fail.

-
Tyle schrieb:
int groesse = 42; int *pArray; pArray = new int[groesse]; delete [] pArray;Und gespickt habe ich da nicht. Das Problem ist das new und delet bei uns auch nur in ca. 10 Zeilen Code erklärt wird.
Das sieht doch gut aus.
Wieso lässt Du Dich dann so verwirren, dass Du den ersten Code schreibst?
Was Du jetzt hast ist ein Array von 42 ints.
Sagen wir ich wollte davon fünfzigtausend Stück haben.
Ergo brauche ich fünfzigtausend Zeiger wiepArray, die jeweils auf 42 ints zeigen.
DapArrayeinint*("Zeiger auf int") ist hat ein Zeiger auf ein solches Array den Typint**("Zeiger auf Zeiger auf int").
In einem ersten Schritt alloziere ich die 50k Zeiger-auf-Zeiger und in einem weiteren für jeden von diesen 42 ints.int main(){ const int dim1=50000, dim0=42; int** ppArray = new int*[dim1]; // Schritt 1: Speicher fuer dim1 mal int* for(int i=0; i<dim1; ++i) // Schritt 2: dim1 mal Speicher fuer dim0 ints ppArray[i]=new int[dim0]; //.... for(int i=0; i<dim1; ++i) delete[] ppArray[i]; delete[] ppArray; }Beachte, dass hinter
newein Typ steht:new int*[size];bedeutet ein Array von int*.
new double**[size];ist dementsprechend ein Array vondouble**
Deine fehlerhafte Syntax sah so aus, als ob Du irgendwas mit einer Größe multiplizieren wolltest um den Speicherbedarf anzugeben.
-
SeppJ schrieb:
Warum nicht
x*ydim0*dim1 an einem Stück?
-
SeppJ schrieb:
SeppJ schrieb:
Warum nicht
x*ydim0*dim1 an einem Stück?Kannst Du dafür nicht einen eigenen Thread aufmachen, wenn Du das diskutieren willst?
Ich schätze dem OP wäre damit nicht bei seinem akuten Problem geholfen.Aber schreib doch die paar Zeilen. Besser als zweimal den gleichen Halbsatz zu posten wird's allemal.
Go for it!
-
Habe ich oben ja schon. Ob man da nun MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy oder einen anderen Container einsetzt ist bewusst anpassbar gelassen.
Es ist aber halt ziemliche Verschwendung, das nicht alles an einem Stück anzufordern. Das würde man niemals so machen, weil es lauter dicke Nachteile hat und man hier keinen der Vorteile benutzt.
-
Wieso lässt Du Dich dann so verwirren, dass Du den ersten Code schreibst?
Das war vorher ein C-Programm mit malloc und free. Darin habe ich dann stümperhaft rumgewerkelt.
@SeppJ Kannst ja mal ne Beispiel für ne Code am Stück liefern.
-
Ok ich glaube ich habe es nun. Scheint auch soweit zu funktionieren bekomme nur eine Warnug zu der time_t Funktion.
Warnung:
quelle.cpp(35): warning C4244: 'Argument': Konvertierung von 'time_t' in 'unsigned int', möglicher Datenverlust#include <cstdlib> #include <ctime> #include <iostream> #include <conio.h> using namespace std; int main() { double **matrix; //Zeiger auf Zeiger auf Matrix int dim; cout << "Dimension eingeben: "; cin >> dim; //Speicher fuer dim x dim Matrix anfordern matrix = new double*[dim]; //Speicher fuer dim mal int* for(int i=0; i<dim; ++i) //dim1 mal Speicher fuer dim ints matrix[i]=new double[dim]; //Mit Zufallswerten fuellen srand(time(NULL)); for(int i=0 ; i<dim ; i++) for(int j=0 ; j<dim ; j++) matrix[i][j] = (double)rand(); //Ausgeben cout << "Erzeugte Matrix: " << endl; for(int i=0 ; i<dim ; i++) { for(int j=0 ; j<dim ; j++) { cout << matrix[i][j] << " "; } cout << endl; } //Speicher wieder freigeben for(int i=0; i<dim; ++i) delete[] matrix[i]; delete[] matrix; _getch(); return 0; }Jetzt kann ich mich an was komplizierteres wagen um zu sehen ob ich das verstanden habe. Danke nochmals für eure Hilfe.
-
Tyle schrieb:
@SeppJ Kannst ja mal ne Beispiel für ne Code am Stück liefern.
SeppJ schrieb:
Habe ich oben ja schon. Ob man da nun MyUnnecessaryAndTediousAndBadCloneOfStdVectorThatOnlyWorksForDefaultConstructibleTypesBecauseIAmLazy oder einen anderen Container einsetzt ist bewusst anpassbar gelassen.
SeppJ schrieb:
template <typename ElementType> class Array2D { private: HierirgendetwasdasElementTypespeichernkannzurnotaucheinenpointermitnew data; unsigned long size_x; public: Array2D(unsigned long size_x, unsigned long size_y) : data(size_x * size_y), size_x(size_x) {} ElementType& operator()(unsigned long x, unsigned long y) { return data[x + y * size_x]; } const ElementType& operator() (unsigned long x, unsigned long y) const { return data[x + y * size_x]; } };
-
Ok ich bin schon ein ganzes Stück weitergekommen aber es werden nach beenden der .exe noch Fehler angezeigt, bzw. da Programm stürzt dann ab.
Auch kann ich keine Dimension größer als 9 benutzen, warum weiss ich nicht.
Code ist noch ein wenig holprig, aber bin ja noch am lernen

Hier mal das Programm:
#include <iostream> #include <iomanip> #include <cmath> #include <conio.h> #define M_PI 3.14159265358979323846 //M_PI wirk komischerweise vom Compiler nicht definiert using namespace std; // Template Prototypefunktion // template <typename T> T dot(T *x, T *y, int n); int main() { //Vektoren int *xi, *yi; float *xf, *yf; double *xd, *yd; bool *xb, *yb; //Matrizen int **I; float **F; double **D1; double **D2; int n; cout << "Bitte Dimension n eingeben: "; cin >> n; //const float M_PI = 3.141; //Speicher reservieren D1 = new double *[n]; for(int i=0; i<n; ++i) D1[i]=new double[n]; D2 = new double *[n]; for(int i=0; i<n; ++i) D2[i]=new double[n]; I = new int *[n]; for(int i=0; i<n; ++i) I[i]=new int[n]; F = new float *[n]; for(int i=0; i<n; ++i) F[i]=new float[n]; xi = new int; yi = new int; xf = new float; yf = new float; xd = new double; yd = new double; xb = new bool; yb = new bool; //Vektoren und Matrizen mit Werten fuellen for(int i=0 ; i<n ; i++) { xi[i] = i+1; yi[i] = i-1; xf[i] = 0.1f*i; yf[i] = 0.25f*i; xd[i] = M_PI*i; yd[i] = 1e-10*i; xb[i] = (i%2 == 0); yb[i] = (i%3 == 0); for(int j=0 ; j<n ; j++) { if(i==j) I[i][j] = 1; else I[i][j] = 0; if(i>j) F[i][j] = 0.2*i; else F[i][j] = 0.2*j; D1[i][j] = M_PI*(i+j); } } cout << setprecision(2); cout << "Skalarprodukt von int Vektoren: " << dot(xi,yi,n) << endl; cout << "Skalarprodukt von float Vektoren: " << dot(xf,yf,n) << endl; cout << "Skalarprodukt von double Vektoren: " << dot(xd,yd,n) << endl; //Speicher wieder freigeben for(int i=0; i<n; ++i) delete[] D1[i]; delete[] D1; for(int i=0; i<n; ++i) delete[] D2[i]; delete[] D2; for(int i=0; i<n; ++i) delete[] I[i]; delete[] I; for(int i=0; i<n; ++i) delete[] F[i]; delete[] F; delete xi; delete yi; delete xf; delete yf; delete xd; delete yd; delete xb; delete yb; _getch(); return 0; } // Template Funktion Definition // template <typename T> T dot(T *x, T *y, int n) { T res = 0; for (int i=0; i<n; i++) res += x[i]*y[i]; return res; }
-
Erklär mal, was du dir bei Zeile 47 ff. gedacht hast.
-
Nun ja ich habe am anfang nur die Matritzen mit new belegt und der Kompiler hat immer die Variablen angemeckert.
Habe daher ne bissel mit trail-and-error rumexperimentiert.
Nachdem ich Speicher für die Variablen allokiert habe hat das Programm soweit (bis das Ende) funktioniert.
-
Tyle schrieb:
Habe daher ne bissel mit trail-and-error rumexperimentiert.
Uralter, aber absolut wahrer Spruch hier aus dem Forum:
c.rackwitz schrieb:
Wenn du selber Code schreibst, musst du ihn auch verstehen. Code ist kein Haufen von wahllos zusammengeschmissenen Buchstaben und Zeichen, Code ist Logik pur. Du musst genau wissen, warum du wo und welches Zeichen setzt.
Studiere diese Aussage genau und lerne daraus.
-
Mit ist schon klar das ich das Programm noch nicht verstanden habe, daher versuche ich das ganze ja zu verstehen.
Meine Materialien sind leider in Bezug auf new und delet sehr sehr dürftig. Muss daher leider viel ausprobieren.
Wäre super wenn mir jemand erklären könnte was ich genau falsch gemacht habe und die Logik dahinter klar macht.
-
Tyle schrieb:
Meine Materialien sind leider in Bezug auf new und delet sehr sehr dürftig. Muss daher leider viel ausprobieren.
newunddeletesind ja auch keine Raketentechnik, da muss man gar nicht soviel schreiben.
Subtil sind allerdings die Anforderungen, die man erfüllen muss, damit man keine Speicherlecks hat. Aber auch dafür haben sich mittlerweile Lösungen gefunden - meistens in der Form, dass man keinnewunddeletebenutzt.
State of the Art sind dagegen Handles:std::string,std::vectorusw. usf..Auch auf die Gefahr hin mich zu wiederholen:
newgibt einen Zeiger auf allozierten Speicher zurück.
Der zurückgebene Zeiger hat einen Typ abhängig vom allozierten Objekt.Für eine einzige Instanz ist die Form
auto a = new int; // a ist int*
für ein Array ist die Form:
auto aa = new double[12]; // aa ist double*, aa zeigt auf's erste ElementSo allozierten Speicher gibt man nach Gebrauch mit
deletewieder frei.
delete a; // a von oben
, bzw.
delete[] aa; // aa von obenSo und jetzt kommst Du und erklärst uns: was Du Dir bei Zeile 47ff gedacht hast.
Bzw. was Du jetzt darüber denkst.
Zur Erinnerung: Du weisst, wie Du Arrays (aka. Vektoren) mitnewanlegst.
-
Also ich glaube ich habe den Fehler gefunden:
Vorher habe ich mit
xi = new int;nur Speicher für einen Int Wert reserviert. Was natürlich totaler Quatsch ist, das xi ein Zeiger vom Typ int ist und somit ein Array da ein Array ja auch nur ein Zeiger auf das erste Element des Arrays ist.
An der Stelle hätte ich es eigentlich schon sehen sollen, das die Werte als Array befüllt werden:
xi[i] = i+1; yi[i] = i-1; xf[i] = 0.1f*i; yf[i] = 0.25f*i; xd[i] = M_PI*i; yd[i] = 1e-10*i; xb[i] = (i%2 == 0); yb[i] = (i%3 == 0);Klar das meine vorherige Zuweisung das Programm zum Absturz gebracht hat, da ja kein Speicher, bzw. viel zu wenig Speicher zugewiesen wurde.
Somit andert sich das Programm wie folgt:
#include <iostream> #include <iomanip> #include <cmath> #include <conio.h> #define M_PI 3.14159265358979323846 using namespace std; // Template Funktion Prototype // template <typename T> T dot(T *x, T *y, int n); int main() { //Vektoren int *xi, *yi; float *xf, *yf; double *xd, *yd; bool *xb, *yb; //Matrizen int **I; float **F; double **D1; double **D2; //Teilaufgabe a) int n; cout << "Bitte Dimension n eingeben: "; cin >> n; //const float M_PI = 3.141; //Speicher reservieren D1 = new double *[n]; for(int i=0; i<n; ++i) D1[i]=new double[n]; D2 = new double *[n]; for(int i=0; i<n; ++i) D2[i]=new double[n]; I = new int *[n]; for(int i=0; i<n; ++i) I[i]=new int[n]; F = new float *[n]; for(int i=0; i<n; ++i) F[i]=new float[n]; xi = new int[n]; yi = new int[n]; xf = new float[n]; yf = new float[n]; xd = new double[n]; yd = new double[n]; xb = new bool[n]; yb = new bool[n]; //Vektoren und Matrizen mit Werten fuellen for(int i=0 ; i<n ; i++) { xi[i] = i+1; yi[i] = i-1; xf[i] = 0.1f*i; yf[i] = 0.25f*i; xd[i] = M_PI*i; yd[i] = 1e-10*i; xb[i] = (i%2 == 0); yb[i] = (i%3 == 0); for(int j=0 ; j<n ; j++) { if(i==j) I[i][j] = 1; else I[i][j] = 0; if(i>j) F[i][j] = 0.2*i; else F[i][j] = 0.2*j; D1[i][j] = M_PI*(i+j); } } cout << setprecision(2); cout << "Skalarprodukt von int Vektoren: " << dot(xi,yi,n) << endl; cout << "Skalarprodukt von float Vektoren: " << dot(xf,yf,n) << endl; cout << "Skalarprodukt von double Vektoren: " << dot(xd,yd,n) << endl; //Speicher wieder freigeben for(int i=0; i<n; ++i) delete[] D1[i]; delete[] D1; for(int i=0; i<n; ++i) delete[] D2[i]; delete[] D2; for(int i=0; i<n; ++i) delete[] I[i]; delete[] I; for(int i=0; i<n; ++i) delete[] F[i]; delete[] F; delete [] xi; delete [] yi; delete [] xf; delete [] yf; delete [] xd; delete [] yd; delete [] xb; delete [] yb; _getch(); return 0; } // Template Funktion Definition // template <typename T> T dot(T *x, T *y, int n) { T res = 0; for (int i=0; i<n; i++) res += x[i]*y[i]; return res; }Sehe ich das so richtig?