Eine Zeichenfolge ist unveränderlich. Warum sind sie nicht alle Konstanten?

8

Der stringTyp ist unveränderlich.

Wir können das constSchlüsselwort mit stringsin einer Hochsprache wie .NET verwenden. Mein Verständnis von 'const' bedeutet konstant (es bleibt gleich, wir können den Wert nicht ändern).

Sind stringsnicht immer constant(IMO sollte der Begriff constantnicht im selben Kontext anwendbar sein, wenn der Typ jedes Mal neu erstellt werden muss, wenn er für die Werte Lebensdauer bedeutet, dass er konstant war)?

Liegt dies in Hochsprachen, insbesondere in .NET (obwohl ich mich auch für Java interessieren würde) an der allgemeinen Speicherverwaltung / -verfolgung von Objekten oder gibt es einen anderen Grund?

Dave
quelle
6
Welche Programmiersprache verwenden Sie? Die Antwort kann von bestimmten Details der Sprachimplementierung abhängen.
Viliam Búr
Ihre Definition von "konstant" ist schwer zu verstehen. Meinst du "einmal erstellt, existiert es immer"? Wenn ja, sollte die Antwort offensichtlich sein: Ihnen würde der Speicher ausgehen.
Parsifal
1
Wenn Sie das nicht meinen, verwirren Sie Objekte und die Variablen, die auf sie verweisen. Eine "Konstante" in Java (und ich nehme auch .Net an) ist einfach eine Variable, die niemals geändert werden kann.
Parsifal
1
@DaveRook In Java verhindert der finalModifikator einer Zeichenfolgenvariablen, dass die Variable so geändert wird, dass sie auf eine andere Zeichenfolge verweist .
1
Was genau muss konstant sein , was kann nicht genau geändert werden: die Zeichen in einem bestimmten Zeichenfolgenobjekt oder ein Objekt in einer bestimmten Variablen? Das sind zwei verschiedene Dinge. In Java - Strings sind unveränderlich , was bedeutet , dass , wenn Sie einen String - Objekt erstellen, Sie nicht können es ändern ... aber man kann es wegwerfen und ein anderes Objekt in die gleiche Variable setzen. Die konstante Zeichenfolge ("statische endgültige Zeichenfolge" in Java) bedeutet, dass Sie das Objekt in der Variablen nicht einmal ersetzen können.
Viliam Búr

Antworten:

22

Sie verwechseln zwei verschiedene Dinge:

  • Unveränderlich bedeutet, dass der Speicherinhalt des Objekts nicht geändert werden kann. Wenn Sie ein unveränderliches Objekt (z. B. a string) ändern , wird der Speicherinhalt dieses Objekts nicht geändert. Stattdessen:

    1. Ein neuer Speicherblock wird zugewiesen.
    2. Der Inhalt des Objekts, das Sie ändern wollten, wird in diesen neuen Block kopiert. Der Teil, den Sie ändern möchten, wird in diesem neuen Block geändert.
    3. Der Zeiger (dh die Referenz) wird diesem neuen Block zugewiesen.
  • Konstante bedeutet, dass die Variable zur Kompilierungszeit nicht geändert werden kann. Ob ein stringoder ein integerInhalt der Variablen (oder worauf sie verweist) kann beim Kompilieren nicht geändert oder zugewiesen werden.

rae1
quelle
Vielen Dank. Ich bin weit zu wörtlich, aber das beantwortet es sehr gut.
Dave
1
Wenn Sie die Konstante zur Kompilierungszeit nicht ändern können, wann ändern Sie sie?
Parsifal
2
@parsifal Wenn es ein ist const, können Sie es nicht ändern. Sie können es einem Anfangswert definieren, aber Sie können ihm nirgendwo anders einen anderen Wert zuweisen, sodass Sie ihn nicht ändern können.
Rae1
@ rae1n: das ist nicht 100% richtig. Konstante bedeutet, dass eine Variable zur Laufzeit nicht geändert werden kann . Es ist eine Eigenschaft der Variablen, die eine Zeichenfolge enthält, während die Unveränderlichkeit eine Eigenschaft des Objekts selbst ist.
Doc Brown
@DocBrown Wollen Sie damit sagen, dass Sie eine Konstante zur Kompilierungszeit ändern können?
Rae1
6

Wie die Kommentare sagen, verwechseln Sie "konstant" mit "unveränderlich", wenn sie wirklich zwei sehr unterschiedliche Dinge bedeuten.

Eine Konstante ist eine Variable , die nicht geändert werden kann. Abhängig von der Sprache und dem Compiler ist es durchaus möglich, dass kompilierter Code einfach jede Verwendung dieser Variablen durch den ihr zugewiesenen Wert ersetzt. In diesem Fall würde ihm niemals ein Speicherplatz zugewiesen. Auch wenn der Compiler nicht auf diese Weise optimiert, wird ihm beim Start (wie constimpliziert static) immer noch ein Speicherplatz zugewiesen und bleibt dort bis zum Beenden.

Ein unveränderlicher Wert ist ein Wert im Speicher , der nicht geändert werden kann (bis der Speicher wiederhergestellt ist). Es wird nach Bedarf ein Speicherplatz zugewiesen und kann (theoretisch) in mehreren Variablen gespeichert werden. Das Zuweisen zu einer Variablen, die auf einen unveränderlichen Wert zeigt, erstellt einfach eine neue unveränderliche und ändert die Variable so, dass sie stattdessen darauf zeigt. Der alte Wert bleibt bis zur Speicherbereinigung im Speicher, was auch während der Ausführung des Programms passieren kann.

Bobson
quelle
3
+1, um zu erklären, was die Konstante tatsächlich tut: Inline-Wert der Variablen überall dort, wo auf sie verwiesen wird; Dies ist ein wichtiger zu verstehender Mechanismus, da er noch größere Auswirkungen hat als nur das, was hier erwähnt wird.
Jimmy Hoffa
2

Saiten können sich nicht ändern. Zeiger auf Zeichenfolgen können sich ändern. Folgendes ist gültiger Code:

String text = "Text";
text = text.substring(1);

Das ursprüngliche "Text" -Objekt ist noch vorhanden, unverändert und unveränderlich, außer dass nichts mehr darauf hinweist. Mit einer veränderlichen Variable Stringkönnen Sie darauf text.substring(1)verzichten, sie der textVariablen wieder zuweisen zu müssen , und das ursprüngliche Objekt wird geändert. Wenn Sie möchten , dass sich die Variable text nicht ändert, machen Sie sie zu einer const. Für beide gibt es gültige Anwendungsfälle.

Nebenbei bemerkt ist dies ein gutes Beispiel für ein Konzept, das in C ++ leichter zu verstehen ist, da Objekte und Zeiger auf Objekte unterschiedliche Typen haben.

Karl Bielefeldt
quelle
1

Ich glaube, dass Sie Variablen und Objekte verwirren.

Eine Variable ist einfach eine Referenz auf ein Objekt .

Während Ihr Programm ausgeführt wird, kann eine Variable auf mehrere Objekte verweisen . Wenn Sie der Variablen etwas zuweisen, wird das Objekt nicht geändert. Wenn es keine Variablen gibt, die auf ein Objekt verweisen, wird es zu Müll.

A Stringwird als unveränderlich angesehen (in Java, und ich würde es auch in .Net erwarten), da es keine Möglichkeit gibt, das Objekt zu ändern .

Eine Konstante ist einfach eine Variable, die sich während der Laufzeit des Programms nicht ändern darf. Sie definieren eine Konstante mit dem finalModifikator in Java und dem constModifikator in .Net.

Wenn Ihre "konstante" Variable jedoch auf ein veränderliches Objekt verweist, wirkt sich die "Konstanz" der Variablen nicht auf die Veränderlichkeit des Objekts aus (tatsächlich kann ich das in .Net nicht mit Sicherheit sagen, da ich davon ausgehe erbt einige der arkanen Regeln von C ++).

Parsifal
quelle
@Downvoter - möchtest du einen Kommentar abgeben? Oder sollte ich davon ausgehen, dass auch Sie den Unterschied zwischen einer Variablen und einem Objekt nicht kennen?
Parsifal
1
Ich bin nicht der Downvoter - aber denken Sie, dass nicht die ganze Welt Java oder C # ist?
Ingo
1
@Igno - na klar, außer dass das OP "speziell .NET (obwohl ich an Java interessiert wäre" sagte, also beschränkte ich meine Kommentare auf diese beiden. Das heißt, die Trennung zwischen Variable und Objekt gilt auch für JavaScript, Ruby, Python , Perl und PHP. Tatsächlich kann ich mir außer C ++ keine andere moderne Sprache
vorstellen
-1

Eine einfache Demonstration dessen, was constbegleitet. Dies gilt für C # und ähnliche Sprachen.

string noconst = "foo";
noconst = "bar"; //noconst has changed! It was declared as "foo" but now is "bar"

const string yesconst = "foo";
yesconst = "bar"; //compiler error
Brian
quelle
1
Dies zeigt zwar, wie constsich das Verhalten verhält, ist jedoch nicht eindeutig const. In Java finalverhält sich das Schlüsselwort ähnlich und in C # macht das readonlySchlüsselwort dasselbe. Das Einzigartige an a constist, dass es zur Kompilierungszeit bekannt ist.
Corbin