Fehler nach Compiler-Update
-
Hatte da eine andere Definition von physischer Constness im Kopf, nämlich die tatsächliche Unmöglichkeit der Veränderung des Wertes (Read-Only-Speicher, z.B.)
Und das ist die meinige

P.S.: Das mit den Funktionen ist soweit ich sehe quatsch. Ich hab da selbst was durcheinander gebracht.
Die Funktion ist halt logisch const, wenn sie (wie ich sagte) nur den logischen Wert des Objektes nicht verändert, jedoch den physikalischen.
Eine Funktion ist dagegen physikalisch const, wenn sie das Objekt gar nicht verändert.
-
Sone schrieb:
Mr X schrieb:
Sone schrieb:
mutable ist dazu da, die physikalische constness auszuheben und daraus eine logische constness zu machen - so, dass selbst in cv-qualifizierten Membermethoden
mutableMember verändert werden können.Das heißt, dass auch in konstanten Methoden diese Member verändert werden können. Mit dem Unterschied von logischer und physikalischer Constness würde ich das jetzt nicht in Verbindung bringen.
Findest du? Find ich nicht.
HIer wieso:
Wenn es keine mutable Member gibt, ist der Speicher der Klasse ja geschützt, damit ist das Object physikalisch const. Wenn es mutable Member gibt, existiert theoretisch nur noch die logische constness- der speicher kann teilweise auch für const-Objekte verändert werden.
Während Du das geschrieben hast, habe ich da noch eine Anmerkung in meinen Beitrag hineineditiert. Hatte eine andere Definition von phyischer/logischer Konstanz im Kopf. Allerdings muss man bei deiner Definition eines bedenken: Es ist möglich, den Speicherinhalt (wenn auch nur mit üblen Hacks) zu verändern, selbst wenn das Objekt physisch Konstant ist.
-
Mr X schrieb:
Allerdings muss man bei deiner Definition eines bedenken: Es ist möglich, den Speicherinhalt (wenn auch nur mit üblen Hacks) zu verändern, selbst wenn das Objekt physisch Konstant ist.
Das wusste ich nicht. Erzähl.

-
Sone schrieb:
Hatte da eine andere Definition von physischer Constness im Kopf, nämlich die tatsächliche Unmöglichkeit der Veränderung des Wertes (Read-Only-Speicher, z.B.)
Und das ist die meinige

P.S.: Das mit den Funktionen ist soweit ich sehe quatsch. Ich hab da selbst was durcheinander gebracht.
Die Funktion ist halt logisch const, wenn sie (wie ich sagte) nur den logischen Wert des Objektes nicht verändert, jedoch den physikalischen.
Eine Funktion ist dagegen physikalisch const, wenn sie das Objekt gar nicht verändert.Nun, ich dachte eher, du definierst es so:
physische Konstanz: Der Speicherinhalt bleibt unverändert.
logische Konstanz: Das Objekt "sieht" von außen gleich aus.
-
Sone schrieb:
Mr X schrieb:
Allerdings muss man bei deiner Definition eines bedenken: Es ist möglich, den Speicherinhalt (wenn auch nur mit üblen Hacks) zu verändern, selbst wenn das Objekt physisch Konstant ist.
Das wusste ich nicht. Erzähl.

Ohne es getestet zu haben:
const int i = 5; int* p = (int*)&i; *p = 6; std::cout << i;Das _kann_ ein Exception auslösen, muss es aber nicht. Hängt vom Compiler/Laufzeitumgebung ab. Es kann auch 6 rauskommen.
Das gleiche kannst Du auch in cv-Methoden tun, indem du den this-Zeiger castest. Das dabei eine Ausnahme geworfen wird, halte ich übrigens für eher unwahrscheinlich.
-
Mr X schrieb:
Sone schrieb:
Hatte da eine andere Definition von physischer Constness im Kopf, nämlich die tatsächliche Unmöglichkeit der Veränderung des Wertes (Read-Only-Speicher, z.B.)
Und das ist die meinige

P.S.: Das mit den Funktionen ist soweit ich sehe quatsch. Ich hab da selbst was durcheinander gebracht.
Die Funktion ist halt logisch const, wenn sie (wie ich sagte) nur den logischen Wert des Objektes nicht verändert, jedoch den physikalischen.
Eine Funktion ist dagegen physikalisch const, wenn sie das Objekt gar nicht verändert.Nun, ich dachte eher, du definierst es so:
physische Konstanz: Der Speicherinhalt bleibt unverändert.
logische Konstanz: Das Objekt "sieht" von außen gleich aus.Ja, so definiere ich es. Für Objekte. Für Funktionen wie oben.
-
Sone schrieb:
Mr X schrieb:
Sone schrieb:
Hatte da eine andere Definition von physischer Constness im Kopf, nämlich die tatsächliche Unmöglichkeit der Veränderung des Wertes (Read-Only-Speicher, z.B.)
Und das ist die meinige

P.S.: Das mit den Funktionen ist soweit ich sehe quatsch. Ich hab da selbst was durcheinander gebracht.
Die Funktion ist halt logisch const, wenn sie (wie ich sagte) nur den logischen Wert des Objektes nicht verändert, jedoch den physikalischen.
Eine Funktion ist dagegen physikalisch const, wenn sie das Objekt gar nicht verändert.Nun, ich dachte eher, du definierst es so:
physische Konstanz: Der Speicherinhalt bleibt unverändert.
logische Konstanz: Das Objekt "sieht" von außen gleich aus.Ja, so definiere ich es. Für Objekte. Für Funktionen wie oben.
Genau. Dann passt deine Bemerkung von oben ja auch.
-
Cool! Der GCC macht es irgendwie komisch, er ignoriert die Anweisung komplett:
const int i = 5; int* p = (int*)&i; *p = 6; std::cout << i; //Ausgabe: 5Dasselbe bei meinem Hack:
int const a(5); memset(const_cast<void*>(reinterpret_cast<void const*>(&a)), 0, sizeof (a)); std::cout << a << '\n'; // 5Mr X schrieb:
Genau. Dann passt deine Bemerkung von oben ja auch.
Puah, schön dass das jetzt endlich geklärt ist

-
Sone schrieb:
Cool! Der GCC macht es irgendwie komisch, er ignoriert die Anweisung komplett:
const int i = 5; int* p = (int*)&i; *p = 6; std::cout << i; //Ausgabe: 5Dasselbe bei meinem Hack:
int const a(5); memset(const_cast<void*>(reinterpret_cast<void const*>(&a)), 0, sizeof (a)); std::cout << a << '\n'; // 5Das sieht so aus, also hat er die Konstante wegoptimiert. Ich probiers mal selbst aus.
-
Im MSVC gehts, da kommt 6 raus.Nein. Mein Fehler. Er wirft eine Ausnahme. Die Compiler sind sicherer, als ich gedacht habe.
-
An den TE: Ich hoffe, dein Problem mit mutable hat sich gelöst. Also nochmal: Mit mutable deklarierte Member dürfen auch in const-qualifizierten Funktionen verändert werden. Es kann also sein, dass in deinem Code vereinfacht folgendes steht:
class FrameworkBla { mutable size_t counter; FrameworkBla(): counter(0) {} void eine_Logisch_Konstante_Funktion() const { ++counter;//Hier wird counter verändert, obwohl die Instanz ja const ist! Ohne mutable wird es also einen einfachen semantischen Fehler geben. ........ } };
-
Was mich noch verwirrt: Sekunde mal! Wenn du deinen Compiler geupdatet hast, heißt das ja, dass der diesen falschen Code vorher geschluckt hat!

Notiz an mich: Dringend meinen GCC updaten.
-
So, jetzt hab ichs aber hingekriegt (Die Spielerei mit dem this-Zeiger funktioniert; Da gibts keine Exception und der Compiler (MSVC) funkt auch nicht dazwischen.):
#include <iostream> struct C { int i; C() : i(5) {} void foo() const { C* c = (C*)this; c->i = 6; } }; int main() { C c; c.foo(); std::cout << c.i; }
-
#include <iostream> struct C { int i; C() : i(5) {} void foo() const { C* c = (C*)this; c->i = 6; } }; int main() { C c; c.foo(); std::cout << c.i; }
Nochmal um das klarzustellen: Auf keinen Fall benutzen! Das ist UB und sehr unelegant.

-
Ramanujan schrieb:
mutable long const& m; //!< matrix row sizeGruselig. Memberreferenzen? Und dann auch noch mutable?
Bestimmt wird dann bei der Zuweisung auch noch wild mit Zeigern und Casts gewerkelt, um die Referenz umzubiegen. Es gibt eben Leute, die wollen sich das Bein wegschießen.Sone schrieb:
#include <iostream> struct C { int i; C() : i(5) {} void foo() const { C* c = (C*)this; c->i = 6; } }; int main() { C c; c.foo(); std::cout << c.i; }
Nochmal um das klarzustellen: Auf keinen Fall benutzen! Das ist UB und sehr unelegant.

Undefiniertes Verhalten findet sich hier nicht.
Das wäre erst dann der Fall, wenn das Objekt c auch const deklariert worden wäre. Der Versuch, ein mit const deklariertes Objekt wärend seiner Lebenszeit (nach Ende des Konstruktors, vor Beginn Destruktor bei Klassen) zu verändern, führt zu undefiniertem Verhalten. Im Umkehrschluss darf der Compiler annehmen, das ein const-deklariertes Objekt nicht verändert wird (und genau deshalb ist der andere Fall undefiniert - es geht in 99% der Fälle von UB um Optimierung. nicht etwa um irgendwelche hardweiseseitig schreibgeschützte Speicherbereiche). und kann somit Zugiffe auf diese konstanten Objekte direkt durch die Werte der initiaiisierenden Ausdrücke ersetzen.
Warum man so etwas überhaupt jemals schreiben wollte, ist auch nicht ganz klar...
-

camper schrieb:
Sone schrieb:
#include <iostream> struct C { int i; C() : i(5) {} void foo() const { C* c = (C*)this; c->i = 6; } }; int main() { C c; c.foo(); std::cout << c.i; }
Nochmal um das klarzustellen: Auf keinen Fall benutzen! Das ist UB und sehr unelegant.

Undefiniertes Verhalten findet sich hier nicht.
Das wäre erst dann der Fall, wenn das Objekt c auch const deklariert worden wäre.Das meinte ich...

Stand so ja in Stroustrups.
-
camper schrieb:
Gruselig. Memberreferenzen?
Was ist an Memberreferenzen so gruselig?
-
Sone schrieb:
Was mich noch verwirrt: Sekunde mal! Wenn du deinen Compiler geupdatet hast, heißt das ja, dass der diesen falschen Code vorher geschluckt hat!

Notiz an mich: Dringend meinen GCC updaten.
Nein, nein. Es ist noch viel besser: 3 verschiedene Versionen haben den Code ohne Fehler oder Warnung kompiliert. Ich hatte vorher 3.4.5, auf dem Unix-Server ist 4.4.3 und wahrscheinlich wird noch eine andere Version auf dem MacBook meines Kollegen sein. Und deshalb hab ich auch erstmal gedacht, dass etwas beim Updaten auf 4.7 schief gegangen ist.
Mr X schrieb:
So, jetzt hab ichs aber hingekriegt (Die Spielerei mit dem this-Zeiger funktioniert; Da gibts keine Exception und der Compiler (MSVC) funkt auch nicht dazwischen.):
#include <iostream> struct C { int i; C() : i(5) {} void foo() const { C* c = (C*)this; c->i = 6; } }; int main() { C c; c.foo(); std::cout << c.i; }Wenn ich diesen Code so sehe, fällt mir auf, dass ich an einer Stelle in meinem Programm auch sowas mache, es ist nur ein wenig komplexer und verworrener. Dann würde es sicher Sinn machen (übertragen auf diesen Beispiel), i als mutable zu deklarieren oder?
Edit:
Wofür steht die Abkürzung UB nochmal wörtlich?camper schrieb:
Ramanujan schrieb:
mutable long const& m; //!< matrix row sizeGruselig. Memberreferenzen? Und dann auch noch mutable?
Bestimmt wird dann bei der Zuweisung auch noch wild mit Zeigern und Casts gewerkelt, um die Referenz umzubiegen. Es gibt eben Leute, die wollen sich das Bein wegschießen.Das ist eine Klasse, die wohl zu Optimierungen da ist. In der ersten Zeile steht auch der Hinweise "// DO NOT USE". Da wird ganz bestimmt wild rumgewerkelt. Ich hoffe mal, dass der Autor alles richtig gemacht hat.
-
Ramanujan schrieb:
Wenn ich diesen Code so sehe, fällt mir auf, dass ich an einer Stelle in meinem Programm auch sowas mache, es ist nur ein wenig komplexer und verworrener. Dann würde es sicher Sinn machen (übertragen auf diesen Beispiel), i als mutable zu deklarieren oder?
Ein besseres Design wäre ggf. vorzuziehen. Obwohl gegen mutable als solches keine theoretischen Einwände bestehen, hatte praktisch keine Bedeutung. Als kanonisches Beispiel wird ja häufig ein transparenter Cache gebracht. Eine Klasse, die so etwas benötigt und auch gleich intern selbst durchführt, kann allerdings kaum vermeiden, zur God-Klasse zu werden. Sobald die Funktionalität entsprechend auf verschiedene Objekte oder Klassen verteilt wird, verschwindet die Notwendigkeit für mutable ganz automatisch.
Ramanujan schrieb:
Wofür steht die Abkürzung UB nochmal wörtlich?
undefined behaviour
Ramanujan schrieb:
camper schrieb:
Ramanujan schrieb:
mutable long const& m; //!< matrix row sizeGruselig. Memberreferenzen? Und dann auch noch mutable?
Bestimmt wird dann bei der Zuweisung auch noch wild mit Zeigern und Casts gewerkelt, um die Referenz umzubiegen. Es gibt eben Leute, die wollen sich das Bein wegschießen.Das ist eine Klasse, die wohl zu Optimierungen da ist. In der ersten Zeile steht auch der Hinweise "// DO NOT USE". Da wird ganz bestimmt wild rumgewerkelt. Ich hoffe mal, dass der Autor alles richtig gemacht hat.
Da bin ich ja beinahe neugierig. Die Wahrscheinlichkeit, dass alles richtig gemacht wurde, ist allerdings sehr gering.
-
camper schrieb:
Ramanujan schrieb:
Wenn ich diesen Code so sehe, fällt mir auf, dass ich an einer Stelle in meinem Programm auch sowas mache, es ist nur ein wenig komplexer und verworrener. Dann würde es sicher Sinn machen (übertragen auf diesen Beispiel), i als mutable zu deklarieren oder?
Ein besseres Design wäre ggf. vorzuziehen. Obwohl gegen mutable als solches keine theoretischen Einwände bestehen, hatte praktisch keine Bedeutung. Als kanonisches Beispiel wird ja häufig ein transparenter Cache gebracht. Eine Klasse, die so etwas benötigt und auch gleich intern selbst durchführt, kann allerdings kaum vermeiden, zur God-Klasse zu werden. Sobald die Funktionalität entsprechend auf verschiedene Objekte oder Klassen verteilt wird, verschwindet die Notwendigkeit für mutable ganz automatisch.
Ich hab mir meine Code nochmal anguckt: Es ist doch ok so, wie ich es gemacht hab: const bleibt const.
[quote="camper"]
Ramanujan schrieb:
Ramanujan schrieb:
camper schrieb:
Ramanujan schrieb:
mutable long const& m; //!< matrix row sizeGruselig. Memberreferenzen? Und dann auch noch mutable?
Bestimmt wird dann bei der Zuweisung auch noch wild mit Zeigern und Casts gewerkelt, um die Referenz umzubiegen. Es gibt eben Leute, die wollen sich das Bein wegschießen.Das ist eine Klasse, die wohl zu Optimierungen da ist. In der ersten Zeile steht auch der Hinweise "// DO NOT USE". Da wird ganz bestimmt wild rumgewerkelt. Ich hoffe mal, dass der Autor alles richtig gemacht hat.
Da bin ich ja beinahe neugierig. Die Wahrscheinlichkeit, dass alles richtig gemacht wurde, ist allerdings sehr gering.
Die Bibliothek heißt CPPLapack. Siehe http://cpplapack.sourceforge.net/. Für Eigenwerte, SVD etc. werden die originalen Lapack-Funktionen genutzt.