it-swarm.com.de

const Referenz und const Zeiger. Wie arbeiten Sie?

Ich habe einen Beitrag darüber gelesen, wie const storage funktioniert.

Wie funktioniert const storage? (Punkt 2, Scott Myers Effective C++)

Dies besagt, dass jedes Segment einen eigenen Abschnitt des schreibgeschützten Speichers hat und konstante Daten dorthin gehen.

Aber was passiert bei Referenzen? Ich möchte drei Szenarien verstehen.

  1. Globale Konstantenreferenz.
  2. const Referenz in der Methode.
  3. const Referenz in einer Klasse.

Und für diese Angelegenheit Zeiger meine ich, obwohl Zeiger in einem schreibgeschützten Abschnitt gespeichert werden können, wie verschiedene Versionen von consts beibehalten werden.

sowie

char x = 'z';
//following can not change the data of x, but ptr itself can change.
const char* ptr = &x;
char y = '9';
ptr = &y;

oben ist erlaubt, aber nicht

char* const ptr1 = &x;
ptr1 = &y;

Wie wird damit umgegangen?

4
Sushil Lakra

Das const in C++ hat zwei Aspekte:

  • logische Konstanz: Wenn Sie eine Variable erstellen und einen const Zeiger oder Verweis darauf zeigen, überprüft der Compiler einfach, ob Sie die Variable nicht direkt oder indirekt über den Zeiger oder die Referenz const ändern . Diese Konstanz kann mit einem const_cast<>. Daher ist der folgende Code vollkommen legal:

    char myString[] = "Hallo Welt!";    //copy the string into an array on the stack
    const char* constPtr = myString;
    const_cast<char*>(constPtr)[i] = 'e';    //perfectly legal
    
  • physische Konstanz: Wenn Sie eine Variable im statischen Speicher erstellen, die const ist, können Sie dem Compiler erlauben, sie in einen nicht beschreibbaren Speicher zu stellen. Es kann dies tun oder nicht. Was den Standard betrifft, rufen Sie einfach undefiniertes Verhalten auf, wenn Sie die Konstanz wegwerfen, um ein solches Objekt zu ändern. Dies schließt alle Zeichenfolgenliterale ein, sodass der folgende Code möglicherweise funktioniert oder nicht:

     const char* myString = "Hallo World!";
     const_cast<char*>(myString)[1] = 'e';     //Undefined behavior, modifying a const static object!
    

Wenn Sie das Qualifikationsmerkmal const wie folgt verwenden:

 const int value=67;

Wir teilen dem Compiler mit, dass wir versprechen, den Wert der Variablen "value" nicht zu ändern. Als solches ersetzt der Compiler lediglich Instanzen von "value" durch den tatsächlichen Wert, mit dem wir ihn initialisiert haben. Da der Compiler jede Instanz der Variablen durch ihren tatsächlichen Wert ersetzt, müssen wir ihn initialisieren.

  const int k; //error,must be initialized.

wenn ein solcher Wert an eine Referenz gebunden wird, muss die Referenz über ein solches Qualifikationsmerkmal verfügen, um sicherzustellen, dass der durch die Referenz gebundene Wert nicht geändert wird (Wertreferenz).

 const int& c1=value;
 c1=56; //error,we cannot modify it through the reference.

wir können aber auch einen Nicht-Konstanten-Wert an eine Konstanten-Referenz binden ...

int i=89;
const int& ic=i; //const lvalue-ref
int& ir=i;
ir=7; //ok.ir is not const
ic=67990; //error ic is const

Wie für Zeiger:

 const int val=90;
 int* valp=&val;//error the pointer is not const.
 const int* val2p=&val;//ok as they are both const
 *val2p =788;//error as it is a pointer to non-writable space

Ein Zeiger auf eine Konstante kann jedoch verwendet werden, um auf ein Nicht-Konstantenobjekt zu verweisen. Die Idee ist, dass Zeiger und Verweise auf Konstanten "denken, dass sie auf Konstantenobjekte zeigen oder auf diese verweisen".

Im Gegensatz zu Referenzen sind Zeiger Objekte und können als const festgelegt werden. Dies bedeutet, dass ein Zeiger auf einen bestimmten Speicher verweisen kann und nach der Initialisierung nicht auf einen anderen Speicher zeigen darf.

 int* const x=&val;//it will point to that memory location only.

Die Tatsache, dass "x" selbst ein Zeiger ist, sagt nichts über den Wert aus, auf den es zeigt.

Der andere interessante Fall ist der Fall "constexpr":

 constexpr int* i=nullptr; //it is the pointer that is const.not the value it points to
 constexpt const int* ii=&value; //both are const in this case.
5
Ricko

Genau genommen fordert const x Den Compiler lediglich auf, zur Kompilierungszeit zu überprüfen, dass Sie x nach seiner ursprünglichen Definition nicht ändern. Dies bedeutet keine Änderung des Laufzeitverhaltens des Programms oder eine Anforderung, den Wert von x anders zu speichern. Ein intelligenter Compiler wird versuchen, dies für einige Optimierungen zu nutzen, aber im allgemeinen Fall kann der Maschinencode, den er für einen konstanten Wert, Zeiger oder eine Referenz generiert, genau der gleiche sein wie für einen nicht konstanten Wert, Zeiger oder eine Referenz. Der einzige Unterschied zwischen const char* Und char* const Besteht darin, dass der Compiler eine andere Prüfung durchführt.

Tatsächlich besteht die Hauptoptimierung hier nicht darin, "const-Variablen" in den statischen schreibgeschützten Programmspeicher zu stellen, sondern dort Literalwerte . In dem von Ihnen angegebenen Beispiel sind die Zeichen 'z' und '9' wahrscheinlich irgendwo in der kompilierten Binärdatei vorhanden, unabhängig davon, für welche Variablen Sie das Schlüsselwort const verwendet haben oder nicht. Wenn Sie längere Zeichenfolgen verwenden, sollten Sie diese mit einem Hex-Editor ganz einfach in der Binärdatei finden können.

Wenn Sie dieses Literal const x Zuweisen, wird der Compiler wahrscheinlich versuchen, die zusätzliche Optimierung durchzuführen, indem x nicht als separater Speicherort dargestellt wird und stattdessen alle Lesevorgänge von x beim Lesen dieses Literalwerts im Programmcode. Aber es würde wahrscheinlich versuchen, dies zu tun, selbst wenn x nicht konstant ist, da es immer noch erkennen kann, dass Sie ihm niemals etwas zuweisen (wenn dies nicht der Fall wäre, wäre es nicht in der Lage, xs const- ness, wenn Sie es deklarieren const). Und es werden wahrscheinlich auch einige Zwischenwerte in CPU-Registern gespeichert, um das Lesen aus irgendeinem Speicher zu vermeiden, sodass der tatsächliche Maschinencode ziemlich stark variiert.

Es ist erwähnenswert, dass eine Menge von C++ - Funktionen auf die gleiche Weise funktioniert. Eine private Klassenmethode ist auch "nur" eine Überprüfung zur Kompilierungszeit.

0
Ixrec

Das Schlüsselwort Const ist eine Anweisung an den Compiler, dass sich sein Anfangswert niemals ändern wird. Der Compiler prüft beim Kompilieren, ob das Programm den Wert auf irgendeine Weise ändert. Bitte klären Sie Ihr Verständnis über konstante Variablen und schreiben Sie geschützte Variablen sind ganz andere Dinge. Es ähnelt der Lehrbuchdefinition von "Variable"

Bei der Programmierung ist eine Variable ein Wert, der sich abhängig von den Bedingungen oder den an das Programm übergebenen Informationen ändern kann. In der Regel besteht ein Programm aus Anweisungen, die dem Computer mitteilen, was zu tun ist, und Daten, die das Programm verwendet, wenn es ausgeführt wird.

Tatsächlich ist Variablen der Name des Speicherorts und kann auch konstant sein.

0
prasad