2013-09-03 3 views
5

Soweit ich in C++ weiß, werden struct/class Mitglieder mit der gleichen Zugriffskontrolle im Speicher in der Reihenfolge der Deklaration gespeichert.Deaktiviert das änderbare Element const-Optimierungen für nicht veränderbare Mitglieder?

#include <cstdlib> 
#include <iostream> 

struct X 
{ 
    mutable int m; 
    int   c; 
}; 

const X cx = {0, 1}; 

int main() 
{ 
    X& x = const_cast<X&>(cx); 

    x.m = rand(); 
    x.c = rand(); 

    std::cout<<x.m<<" "<<x.c; 
} 

das Programm ausgeführt wird und druckt 2 Zufallszahlen In diesem Beispiel: Als nächstes wird Beispiel m und c sollten nacheinander gespeichert werden. Wenn ich mutable entferne, stürzt es ab, weil cx im schreibgeschützten Speicher gespeichert wird. Diese

machte mich fragen - ist ein mutable Mitglied const Optimierungen für die gesamte struct deaktivieren (irgendwie alle Mitglieder machen mutable)?

Ist es möglich, Teile eines struct in Nur-Lese-Speicher und andere Teile auf Nicht-Nur-Lese-Speicher und Respekt C++ Standard-Speicherlayout zu speichern?

Dies wurde mit Visual Studio 2010 unter Windows 7 und GCC 4.7.2 unter Ubuntu getestet.

Antwort

4

Um zu erklären, warum der Compiler "alles oder nichts" zu tun hat, wenn es darum geht, die struct zu speichern: In den meisten Prozessoren sind Speicherseiten 4KB (einige hat 8KB Seiten). Das ist die Granularität von "read only" gegenüber "read/write" Speicherblöcken. Sie können also nicht eine 4-Byte-Ganzzahl im Nur-Lese-Speicher und dann die nächste 4-Byte-Ganzzahl im Lese-Schreib-Speicher haben (es sei denn, sie spreizen genau eine 4KB-Speichergrenze), aber das würde definitiv zu verschwenderischem Nutzen führen Speicher, wenn Sie ein Array von 3000 von ihnen haben, die 12MB nehmen).

Beachten Sie, dass dies keine "Optimierung" ist. Nur-Lese-Speicher ist nicht schneller als Lese-Schreib-Speicher. Es ist ein Schutz gegen Benutzer albern mit const und Schreiben auf die Daten, die sie nicht schreiben sollten.

Auch wenn Sie einen Konstruktor hinzu, die zu Ihrem struct „etwas tut“, es wird höchstwahrscheinlich speichert die Struktur in Schreib-Lese-Speicher, weil es ziemlich schwierig für die Compiler Code generieren schreibgeschützt ein- und ausschalten zur Laufzeit.

+0

Ich habe X() -Konstruktor hinzugefügt, dass inits m und c und cx nicht im schreibgeschützten Speicher wie zuvor ist. Sehr interessante Einsicht, danke! – Felics

1

Das Schlüsselwort "const" ist eher eine Bezeichnung für das Programmierer-Team wie "private" und "public", keine Compiler-Anweisung oder Compiler-Hinweis. Ein Compiler kann ihn zur Optimierung verwenden, muss dies aber nicht. Der Compiler muss nur den Missbrauch kontrollieren und verhindern. Das Verhalten, das du siehst, ist völlig in Ordnung. Und nein, es ist unmöglich, dass Teile einer Struct-Instanz oder Klasseninstanz in verschiedenen Speicherbereichen existieren (zähle das Mapping nicht ein). Weil diese Entscheidung die Verwendung der Struktur beeinflussen würde und vom Programmierer erlaubt werden muss.

+0

"Stichwort" Const "ist mehr ein Label für das Programmierer-Team" - Ich fürchte, dass in diesem Fall Mitglieder dieses Teams leicht unterschiedliche Meinungen darüber haben können, was dieses Label bedeutet. – SChepurin

+0

Ich meine, dass die gute Erklärung wäre - "Das const-Qualifikationsmerkmal ist eine Anweisung an den Compiler, Code zurückzuweisen, der versucht, dieses Objekt direkt zu modifizieren; Versuche, das Objekt indirekt zu modifizieren ... führt zu undefiniertem Verhalten, dh jedes Ergebnis ist möglich . " (http://stackoverflow.com/questions/4275504/deep-analysis-of-const-qualifier-in-c) – SChepurin

+0

Sie haben Recht. Meine Antwort wurde in Eile geschrieben. Trotzdem ist es meiner Meinung nach menschlicher lesbar. Und ja, ich arbeite seit Jahren in verschiedenen Teams und bin immer wieder überrascht, wie die Leute versuchen, den Compiler auszutricksen und zu erwarten, dass er das richtig macht. –

5

Der Standard spricht an vielen Orten über mutable Mitglieder. Ich zitiere unter drei Teile der Norm zu erklären, dass Sie nur die mutable Mitglieder eines const Objekt ändern können. Ansonsten ist es Undefined Verhalten.

3.9.3 CV-Qualifikation [basic.type.qualifier]

A const Objekt ist ein Objekt vom Typ const T oder eine nicht änderbare Subobjekt eines solchen Objekts.

[...]

7.1.1 Speicherklassen-Spezifizierer [dcl.stc]

Der mutable Spezifizierer auf einer Klassendatenelement zunichte macht einen const Spezifizierer an die enthält Klassenobjekt angewendet und ermöglicht die Änderung des Klassenelements mutable, obwohl der Rest des Objekts const ist.

[...]

7.1.6.1 die CV-Qualifikation [dcl.type.cv]

jedoch jedes Klassenmitglied erklärte mutable (7.1.1) kann modifiziert werden, jeder Versuch, ein const Objekt während seiner gesamten Lebensdauer (3.8) ergeben undefiniertes Verhalten zu ändern.


Ist es möglich, Teile eines struct in Nur-Lese-Speicher und andere Teile auf Nicht-Nur-Lese-Speicher und Respekt C++ Standard-Speicherlayout zu speichern?

Nein, ist es unmöglich, einen Teil eineine struct (oder class) in einem anderen Speicherbereich zu speichern, als der Rest des Objekts.

+0

Also die 'x.c = rand();' in 'main' löst in beiden Fällen UB aus, richtig? – Hulk

+0

@Hulk Ja, das 'mutable' Schlüsselwort auf' m' ändert nichts für 'c'. Sehen Sie sich diesen Beitrag an: http://StackOverflow.com/a/583150/1394283. Es erklärt gut den letzten Teil des Standards, den ich zitiere. –

Verwandte Themen