Probleme mit dynamischen Arrays (malloc und free)
-
@DocShoe sagte in Probleme mit dynamischen Arrays (malloc und free):
Du solltest Objekte bei Funktionsaufrufen per Referenz übergeben, nicht per Value. Wenn sie in der Funktion nicht verändert werden auch gern als const-Reference.
Das ist die Erklärung, die ich gebraucht habe, danke. Ich werde es ändern!
@Jockelx sagte in Probleme mit dynamischen Arrays (malloc und free):
Ich habe die Berechnung der Determinante außerhalb der Klasse.
Warum?
Sollte ich das mit anderen Methoden auch so handhaben?
Wenn du dir die Frage von oben beantwortest, dann weisst du doch auch, ob es bei anderen Funktionen ebenfalls sinnvoll ist.
Dass ich Determinante auslagerte, liegt daran, dass ich hier im Forum herausfinden wollte, ob die Trennung der Funktionalität so gemeint war.
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
In dem Sinne finde ich Bezeichner wie getSize als Memberfunktion eher ungünstig. size wäre da verständlicher.
Dass das angesprochen würde, habe ich mir gedacht, da size() ja so öfter zu finden ist. Ich sag mal so, das ist eine schlechte Lösung gewesen, das dämmerte mir schon. Ich werde deinen Rat selbstverständlich umsetzen, danke sehr.
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
Destruktor ist unnnötig. Googel nach 'Rule of 0' für Hintergrundwissen. Oder ohne Hintergrundwissen: Die Funktion ist doch sicher leer bei dir. Dann lass sie doch weg.
Damit liegst du sehr richtig. Als ich den Destruktor erstellte, war hier noch free() drin verarbeitet. Das habe ich entsorgt und der Destruktor blieb verkümmert zurück. Klar, den brauche ich nicht, aber so ist sie, die Evolution.
Bzgl. Rule of Five:
Mein Cpp-Buch vom Author Jürgen Wolf besagt grob vier Punkte:- fertige Container verwenden (in meinem Fall den std::vector<double>)
- Smart Pointer nutzen (hierzu werde ich mich in Kürze genauer einlesen)
- durch Smart Pointer sind delete und delete[] unnötig (steigende Konsistenz des Speichers)
- keine Regel der Rule of Five definieren, sondern das dem Compiler überlassen (das verstehe ich nicht, da ich ja mindestens den Zuweisungsoperator brauche, nicht?)
Ich danke auf jeden Fall für den Verweis auf solche Faustregeln. Es ist sicher gut, solche zu verstehen, um sie sinnvoll anzuwenden. Ich stehe grad allerdings zwischen den Fronten von Rule of Zero und Rule of Five, hier habe ich Nachholbedarf.
@john-0 sagte in Probleme mit dynamischen Arrays (malloc und free):
solange Du nicht weißt wie man die rule of five correct umsetzt.
Diese Regel habe ich mir gestern bereits angeschaut, aber erkenne den Sinn nicht. Wahrscheinlich, weil ich gar keine Notwenigkeit erkenne.
Es gibt:- Kopierkonstruktor (den ich nicht nachvollziehe, da man ja statt einer Referenz die Kopie direkt übergeben könnte, statt aus der Referenz eine Kopie zu machen),
- Destruktor (der zum "Aufräumen" belegter Ressourcen wichtig ist),
- Zuweisungsoperator (der ja in den allermeisten Programmen sowieso verwendet wird),
- Verschiebekonstruktor (der in Fällen, wo Kopieren keine Option ist, sinnvoll zu sein scheint; einen Nutzen sehe ich persönlich für mein Programm nicht.
- Verschiebezuweisung (mein schlaues Buch kennt das, ich noch nicht)
Bisher habe ich mich in das Thema der Rule of Five nicht einarbeiten können, wahrscheinlich auch, weil ich für meine Zwecke keinen Bezug finde.
@Swordfish sagte in Probleme mit dynamischen Arrays (malloc und free):
tu den t-tor weg. das bringt nix.
Ich weiß leider nicht, was du mit t-tor meinst, entschuldige.
Ich freue mich sehr über das nette Miteinander, denn ich fühle mich sehr geholfen, danke!
Lernen ist ja immer ein Prozess, manchmal flüssig, oft zäh, und die Konversation mit euch beschleunigt meinen Prozess ungemein!
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
Bzgl. Rule of Five:
Mein Cpp-Buch vom Author Jürgen Wolf besagt grob vier Punkte:- fertige Container verwenden (in meinem Fall den std::vector<double>)
- Smart Pointer nutzen (hierzu werde ich mich in Kürze genauer einlesen)
- durch Smart Pointer sind delete und delete[] unnötig (steigende Konsistenz des Speichers)
- keine Regel der Rule of Five definieren, sondern das dem Compiler überlassen (das verstehe ich nicht, da ich ja mindestens den Zuweisungsoperator brauche, nicht?)
Hier hat Herr Wolf ausnahmsweise mal Recht, aber allgemein gilt leider Bücher von Jürgen Wolf sind zum Lernen ungeeignet.
-
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
aber allgemein gilt leider Bücher von Jürgen Wolf sind zum Lernen ungeeignet.
Okay, welches Buch oder welche Bücher sind denn zum Lernen geeignet?
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
Ich weiß leider nicht, was du mit t-tor meinst, entschuldige.
t-tor = d-tor mit Tippfehler. = destructor. Einen leeren hinschreiben ist wie sowas.
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
aber allgemein gilt leider Bücher von Jürgen Wolf sind zum Lernen ungeeignet.
Okay, welches Buch oder welche Bücher sind denn zum Lernen geeignet?
Diese Liste wird recht gut gepflegt:
https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282
-
Ich wollte mich eben um die Referenzen bemühen, aber bin auf Probleme gestoßen.
Gegeben bspw. meine Operatorenüberladungen:// operator overloading Matrix operator- (); //unary friend Matrix operator+ (Matrix m, Matrix n); friend Matrix operator- (Matrix m, Matrix n); friend Matrix operator* (Matrix m, Matrix n); friend Matrix operator* (Matrix m, double d); friend Matrix operator* (double d, Matrix m);
So, wie sie gerade sind, kann ich mit
Matrix h = Matrix(3, { 1, 1, 0, 2, -40, 5, 20, 6, -3 }); Matrix g = Matrix(3, { 7, 5, 0, 81, -6, 8, -10, 0, 2 });
problemlos Ausdrücke wie
((4 * h) * -(g * h)).print();
nutzen.
Aber schon wenn ichfriend Matrix operator* (Matrix& m, Matrix& n);
habe, gibt es Probleme, weil ich in vielen Situationen ja keine Objekte habe, von denen referenziert wird.
Auch wenn ich im Konstruktor von Matrix den std::vector<double> referenziere, kann ich obige Deklaration mit { ... } nicht mehr nutzen.Wie wird das dann gehandhabt?
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
Diese Liste wird recht gut gepflegt:
https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282Danke, da stöbere ich mal die Tage.
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
weil ich in vielen Situationen ja keine Objekte habe, von denen referenziert wird.
Bahnhof. Kompilierbares Minimalbeispiel oder das ist nie passiert.
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
gibt es Probleme
Aha. Welche?
Vermutlich würde const helfen.
friend Matrix operator* (const Matrix& m, const Matrix& n);
-
Da ich Matrizen nutze, möchte ich sie in mathematischen Formeln verwenden.
Das bedeutet, dass((4 * h) * -(g * h))
eine Matrix ergeben soll. Ich müsste sonst für jede Teilrechnung ein Objekt erstellen und das ist schwer suboptimal.
-
@manni66 sagte in Probleme mit dynamischen Arrays (malloc und free):
Aha. Welche?
Der Compiler verweigert den Dienst, weil die Operationen nicht definiert seien.
@manni66 sagte in Probleme mit dynamischen Arrays (malloc und free):
Vermutlich würde const helfen.
Gerade getestet, aber bei
Matrix operator* (const Matrix& m, const Matrix& n) { //... }
lässt der Compiler diesen Aufruf nicht mehr zu:
if (!(m.getColumns() == n.getRows())) { //...}
Dann kann ich nicht mehr auf Klassenmethoden von m und n zugreifen.
-
@Rav1642 Du zeigen was Du geschrieben und erklären was für Probleme Du haben.
-
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
lässt der Compiler diesen Aufruf nicht mehr zu:
if (!(m.getColumns() == n.getRows())) { //...}
@SeppJ sagte in Probleme mit dynamischen Arrays (malloc und free):
Guck dir auch das Thema 'const-correctness' an. So etwas wie getSize() sollte const sein. Das ist auch etwas, was du jetzt wahrscheinlich nicht unbedingt machen musst, aber du könntest später Probleme bekommen, wenn du es nicht tust. Und wenn du dann Probleme bekommst, musst du gleich sehr viel ändern
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
Der Compiler verweigert den Dienst,
Aha
Matrix.cpp C6666: Dienst verweigert
Fehlermeldung: Copy&paste
-
#include "Matrix.h" #include <iostream> int main() { Matrix h = Matrix(3, { 1, 1, 0, 2, -40, 5, 20, 6, -3 }); Matrix g = Matrix(3, { 7, 5, 0, 81, -6, 8, -10, 0, 2 }); ((4 * h) * -(g * h)).print(); std::cin.get(); return 0; }
mit
friend Matrix operator* (Matrix& m, Matrix& n);
in Class Matrix in matrix.h bewirkt, dass der mittlere Multiplikationsoperator * bei
((4 * h) * -(g * h))
rot unterstrichen ist.
Der Compiler sagt dann:
Kein "*"-Operator stimmt mit diesen Operanten überein.
Operandentypen sind: Matrix * Matrix
-
@Rav1642 Hst du die Antwort von @manni66 gelesen? Eine bessere Antwort wirst du nicht mehr kriegen: const!
-
@manni66 sagte in Probleme mit dynamischen Arrays (malloc und free):
@Rav1642 sagte in Probleme mit dynamischen Arrays (malloc und free):
Der Compiler verweigert den Dienst,
Aha
Da stand ja die Begründung hinter, das hat ja nichts mit copy und paste zu tun.
Ich habe in den letzten paar Tagen einiges gelernt. Dass ich die große Menge an Vorschlägen und Hinweisen bis hier hin noch nicht vollständig durchgearbeitet und verstanden habe, liegt sicher nicht an fehlendem Wille.
Ich bemühe mich, möglichst viel von dem umzusetzen, was mir hier geraten wird. Ich setze ja nicht nur Recherchen, Codeoptimierungen und Fehlerkorrektur um, sondern schreibe ja auch die Methodenkörper. Da muss ich meine Zeit, die ich am Tag für C++ nutzen kann, sinnvoll aufteilen und habe noch nicht alles auf dem Schirm, entschuldige.
-
Ja, das ist die fehlende Const-correctness, die dich jetzt beißt. Bei einfachen Ausdrücken wärst du vielleicht ohne weg gekommen, aber hier werden temporäre Ausdrücke erzeugt, und der Compiler hält sich selber natürlich ganz strikt an const-correctness. Das heißt, die Const-heit der temporären Ausdrücke sorgt dafür, dass sie nicht zu der Signatur deiner Multiplikationsfunktion passen, die (fälschlich) zwei nicht-const werte erwartet.
Nun ist der Zeitpunkt gekommen, vor dem ich gewarnt habe, an dem du sehr viel ändern musst. Denn so ein const ist ansteckend. Wenn du die Referenzen zu dem Multiplikationsoperator nun korrekt const machst, wird es gewiss sofort oder bald an anderen Stellen zu Problemen kommen, wo du auch const fälschlich weggelassen hast. Letztlich wirst du alles const-correct machen müssen. Solltest du aber sowieso. Const ist schließlich nicht dazu da, um dich zu ärgern, sondern ein Hilfsmittel, das dir hilft, Fehler zu finden.
-
@Jockelx sagte in Probleme mit dynamischen Arrays (malloc und free):
Hst du die Antwort von @manni66 gelesen? Eine bessere Antwort wirst du nicht mehr kriegen: const!
Klar, ich halte mich stets auf dem Laufenden!
Ich sehe, dass da mehr zu tun ist und kann das erst heute Abend umsetzen.Aber warum ist const hier die Lösung?
Als Argument erwarte ich ein Objekt, auf das ich referenzieren kann, aber bei((4 * h) * -(g * h))
sind g und h zwar Objekte, allerdings die Matrizen nicht, die im letzten Schritt multipliziert werden. Also übergebe ich der Funktion ja kein Objekt. Also kann ja auf nichts referenziert werden, oder nicht? Warum kann ich mit const dann auf etwas referenzieren, das man doch eigentlich nicht referenzieren kann?
Das entzieht sich aktuell leider meinem Verständnis.Ich danke für die Antwort!
-
Der Compiler kann (offiziell) nicht in deine Funktionen gucken. Der sieht nur die Signatur deiner Multiplikationsfunktion. Die nimmt nicht-const-Referenzen als Argument. Das heißt, potentiell könnte diese Funktion ihre Argumente ändern, im Sinne von:
void foo(int &i) { i=4;}
Jetzt willst du diese Funktion auf das temporäre Zwischenergebnis deiner Rechnung anwenden. Das wäre im obigen Beispiel ungefähr so wie
foo(3 * 7);
Und das wäre ja totaler Quatsch, da du nicht das Ergebnis von 3 * 7 auf 4 setzen kannst. Und da der Compiler nicht ausschließen kann, dass dein Multiplikationsoperator so etwas nicht tut, lässt er das nicht zu. Wäre im oberen Beispiel hingegen
void foo (const int &i) {...}
dann wüsste er ganz sicher, dass i nicht geändert wird, und er könnte
foo
sorgenlos auf konstante Ausdrücke anwenden.
-
Alle erzeugten Matrix-Instanzen sind Objekte und können referenziert werden (egal ob direkt oder als temporäre Ausdrücke).
Der wichtige Unterschied bzgl. der Parameter
Matrix
undMatrix &
(bzw.const Matrix &
) ist, daß bei ersterem das ganze Matrix-Objekt kopiert wird, während bei der Übergabe mittels Referenz (oder auch mittels Zeiger) intern nur die Adresse des Objekts übergeben wird.
-
@Th69 Maximal verwirrende Antwort...
Um value oder reference geht es gar nicht, sondern darum, dass man eben nicht temporäre Objekte an nicht-const Referenzen binden kann.