[C++] Zeiger, Referenzen, Variablen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von CodingCat »

@Sternmull: Nein, ich sehe dieses Potential eben an dieser Stelle nicht in dieser Allgemeinheit.

Werden Daten für den lokalen Geltungsbereich einer Funktion übergeben (also nicht Referenzen auf diese Daten über den Ablauf der Funktion hinaus gespeichert), so kann die Umgebung außerhalb dieser Funktion diese Daten innerhalb dieses Ablaufzeitraums nicht verändern, da sich der aufrufende Thread gerade ausschließlich innerhalb der aufgerufenen Funktion bewegen kann. Änderungen durch parallel ablaufende Threads an den übergebenen Daten wären in allen Fällen falsch, da in diesem Fall schon bei Aufruf die Kopie und Übergabe der richtigen Werte reiner Zufall wäre (wäre der Zugriff bei Übergabe synchronisiert, dann wäre er das entsprechend der ersten Beobachtung auch für den Ablauf der gesamten aufgerufenen Funktion).

Recht gebe ich dir in Bezug auf Funktionen mit Seiteneffekten, diese können selbstverständlich durch den Aufruf weiterer Funktionen versehentlich den Wert übergebener referenzierter Daten ändern. In diesem Fall muss sich der Programmierer auf jeden Fall der Konsequenzen bewusst sein und ggf. auch eine Kopie in Erwägung ziehen, insbesondere wenn die Auswirkungen der durch die seiteneffektbehaftete Funktion aufgerufenen "Unterfunktionen" nicht absehbar sind.

Nachtrag: @Krishty: Richtig, hier also eine themenbezogenere Antwort, die wohl in Teilen auch schon in deiner steckt.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von Krishty »

Ja, von mir auch ein Dito.

Und was Unterfunktionen angeht, ist das ein Aliasingproblem und es eine Schande, dass es restrict nicht in den Standard geschafft hat.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von CodingCat »

Wobei mir auffällt, dass ich eben die Unterfunktionen zu sehr zur zentralen Bedingung gemacht habe, das Aliasing-Problem kann natürlich auch schon viel früher auftreten, wie z.B. klassisch in der Vektorklasse bei push_back-Operationen mit Elementen des gerade veränderten Vektors, oder wesentlich subtiler auch bei Matrixmultiplikationen mit identischen in/out-Objekten...
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von Krishty »

Ja, aber wie kritisch ist das tatsächlich? Um bei dem Beispiel mit der Benutzereingabe zu bleiben: Diese Funktion wird Benutzereingaben nur verarbeiten, nicht bearbeiten. Bei mir ist es schon ziemlich selten, dass ich zwei Instanzen derselben Klasse erwarte und dann auch noch schreibend auf eine davon zugreife. Und Unterfunktionen operieren nur auf den Daten, die auch die Superfunktion hat – Globaldeklariertes ausgenommen. Gute Kapselung sollte automatisch dafür sorgen, dass man nur auf einem sehr engen Satz Daten operiert und damit auch das Überlappungsrisiko senken.

Aber ein Restrisiko bleibt natürlich immer, so lange man nicht restricten kann. Schade.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
mär
Beiträge: 5
Registriert: 15.03.2011, 16:32

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von mär »

Krishty hat geschrieben:
Sternmull hat geschrieben:Denn dann ist sichergestellt das der Empfänger (die aufgerufene Funktion) mit der Kopie arbeiten kann ohne das anderer Code versehentlich doch an dem Objekt rüttelt.
Und ich will genau andersrum sagen, dass man das von allem erwarten kann, was nicht volatile deklariert ist (und sich nicht mit Dingen überlappt, die die Funktion wissentlich selber modifiziert – aber Aliasing ist ja wieder ein Thema für sich), auch ohne Kopie.

Ich möchte nur nicht den Mund zu weit aufreißen, so lange ich nicht die Paragraphen finde, nach denen das Programm ill-formed ist, falls sich etwas nicht volatile deklariertes durch wen anders ändert.
Nur so am Rande: Es gibt afaik auch bei Verwendung des const Interfaces, legal "mutierende" Eigenschaften, die folglich nicht als volatile deklariert sind...
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von Krishty »

Zum einen sprechen wir immernoch von Veränderungen, die durch fremde Programmteile geschehen (die also nicht durch const abgedeckt werden) und zum anderen ist mutable zur Markierung von Daten gedacht, die zwar den bitweisen, nicht aber den logischen Zustand eines Objekts verändern (mit Caches als klassischem Beispiel). Sowohl const als auch volatile beziehen sich auf das abstrakte Konzept eines Objekts – Byte-weise Veränderungen kann man schon allein deshalb nicht kontrollieren, weil außer dem Compiler niemand ausreichend Kontrolle über die Byte-weise Auslegung des Programms (Padding etc) hat; werden sie öffentlich benutzt oder beruht gar die Programmstabilität auf ihnen, hat man arg was falsch gemacht.

Aber der Vollständigkeit halber ist es natürlich schon gut zu wissen; klar.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
mär
Beiträge: 5
Registriert: 15.03.2011, 16:32

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von mär »

Ich meine bezüglich den Fremdeinwirkungen, dass wenn ein mutierendes, von Threads durchlaufenes Objekt an eine Methode/Routine übergegeben wird, wird const die Veränderung aus Sicht des callee auch nicht verhindern können, sofern die Threads eine Eigenschaft ändern die zu logischen Veränderungen des Objektes führt.

Das ist so aber vermutlich nicht im Sinne des Erfinders. Was bringt denn eine mutable Member praktisch "überhaupt"? Wenn sie schon explizit für das const Interface zur verfügung steht, aber nicht die Sicht verändern darf?

Vermutlich habe ich den Begriff "ill-Formed" aber falsch verstanden, glaube ich.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Zeiger, Referenzen, Variablen

Beitrag von Krishty »

mär hat geschrieben:Was bringt denn eine mutable Member praktisch "überhaupt"? Wenn sie schon explizit für das const Interface zur verfügung steht, aber nicht die Sicht verändern darf?
Wie gesagt, Caches sind das Musterbeispiel – z.B. bei einem Datenbankobjekt, das sich seine Einträge mühsam von einem langsamen Medium zusammensucht. Die Datenbank verändert sich nicht, wenn du einen Wert abfragst; darum ist sie für Funktionen, die bloß Werte abfragen, const deklariert. Nun stehst du aber vor dem Dilemma, dass dein Cache nutzlos ist, wenn du nicht reinschreiben kannst. Darum deklarierst du ihn mutable.

Das ist eine vollkommen saubere Vorgehensweise, weil sich der logische Zustand des Datenbankobjekts nicht ändert, wenn du einen Wert abfragst und der in den Cache wandert – obwohl sich der Byte-weise Zustand natürlich sehr wohl ändert, weil im Cache nun andere Daten stehen als vorher. Das ist aber für niemanden, der damit arbeitet, von Belang – const bedeutet nicht, dass in einem Ding immer dieselben Bytes drinstehen, sondern, dass sich das Objekt in seiner äußeren Erscheinung nicht verändert.

Wenn man mutable einfach nur einsetzt, um den Compiler zur Ruhe zu bringen wenn er wegen const-Correctness meckert, ist das aber falsch. Ebenso, wenn man solche Attribute public macht und andere Programmteile darauf fußen – dann kann man auch gleich auf const-Correctness verzichten. Sich dagegen schützen, dass jemand sowas tut, geht nicht – zur Not kann man in C++ schließlich alle Schutzmechanismen irgendwie aushebeln. Der Sprachentwurf sieht auch nicht vor, sowas zu verbieten, sondern, es so unangenehm wie möglich zu machen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten