2017-01-20 2 views
1

In D-Zeichenfolge ist Alias ​​auf unveränderlich char[]. Also jede Operation zur Stringverarbeitung mit Speicherzuordnung. Ich bin gebunden, um es zu überprüfen, aber nach dem Ersetzen des Symbols in der Zeichenfolge sehe ich die gleiche Adresse.Zuordnungsspeicher für Zeichenfolge

string str = "big"; 
writeln(&str); 
str.replace("i","a"); 
writeln(&str); 

Ausgang:

> app.exe 
19FE10 
19FE10 

Ich versuchte Verwendung ptr:

string str = "big"; 
writeln(str.ptr); 
str.replace(`i`,`a`); 
writeln(str.ptr); 

Und bekam nächste Ausgabe:

42E080 
42E080 

es also die gleiche Adresse zeigt. Warum?

Antwort

2

Sie haben einen einfachen Fehler im Code:

str.replace ("i", "a");

str.replacekehrt die neue Zeichenfolge mit dem Ersatz getan, ist es nicht tatsächlich die existierende Variable ersetzen. Versuchen Sie also str = str.replace("i", "a");, um die Änderung zu sehen.

Aber Sie haben auch eine zu breit allgemeine Aussage über Zuweisungen:

So jede Operation auf String-Verarbeitung mit Zuweisung von Speicher.

Das ist falsch, eine große Anzahl von Operationen erfordern keine Zuweisung von neuem Speicher. Alles, was die vorhandene Zeichenfolge in Scheiben schneiden kann tun so, vermeiden, um neue Speicher:

import std.string; 
import std.stdio; 

void main() { 
     string a = " foo "; 
     string b = a.strip(); 
     assert(b == "foo"); // whitespace stripped off... 

     writeln(a.ptr); 
     writeln(b.ptr); // but notice how close those ptrs are 
     assert(b.ptr == a.ptr + 2); // yes, b is a slice of a 
} 

replace wird auch die ursprüngliche Zeichenfolge zurückgeben, wenn kein Ersatz wurde tatsächlich getan:

string a = " foo "; 
string b = a.replace("p", "a"); // there is no p to replace 
assert(a.ptr is b.ptr); // so same string returned 

Indizierung und Iteration erfordern keine neue Zuteilung (natürlich). Ob Sie es glauben oder nicht, aber selbst das Anhängen wird manchmal nicht zugewiesen, weil am Ende des Slices noch Speicher vorhanden sein kann, der noch nicht benutzt wird (obwohl es normalerweise möglich ist).

Es gibt auch verschiedene Funktionen, die Bereichsobjekte zurückgeben, die die Änderungen ausführen, während Sie sie durchlaufen, um eine Zuordnung zu vermeiden. Zum Beispiel könnten Sie anstelle von replace(a, "f", ""); etwas wie filter!(ch => ch != 'f')(a); und loop through ausführen, das keine neue Zeichenfolge zuweist, es sei denn, Sie fragen es.

Es ist also viel nuancierter, als Sie vielleicht denken!

+0

Welcher Unterschied zwischen 'string * str_ptr; str_ptr = &str; writeln (str_ptr); 'und' writeln (str.ptr); ' –

+0

' & str' ist ein Zeiger auf das ARRAY, 'str.ptr' ist ein Zeiger auf den INHALT. –

0

In D sind alle Arrays eine Länge + ein Zeiger auf den Anfang der Array-Werte. Diese werden normalerweise auf dem Stapel gespeichert, der zufällig RAM ist.

Wenn Sie eine Adresse einer Variablen nehmen (die in einem Funktionskörper ist), was Sie wirklich tun, erhalten Sie einen Zeiger auf den Stapel.

Um die Adresse eines Array-Werte zu erhalten, verwenden Sie .ptr. Ersetzen Sie also &str durch str.ptr und Sie erhalten die richtige Ausgabe.

+0

Ich habe es getestet und es ist die gleiche Adresse anzeigen. Se meine letzte Themenbearbeitung. –

Verwandte Themen