2017-09-20 2 views
3

ich es eigene Inhalte eine variable Referenz machen wollte $$x ist das gleiche wie $x. Was ich erwartet habe ist, dass $$x die ursprüngliche Zeichenfolge wird. Warum ist das und wie sollte ich es richtig schreiben, ohne eine Kopie der Zeichenfolge in $x? Denn in manchen Fällen kann $x eine riesige Zeichenfolge sein.variable Referenz Stellen seinen eigenen String Inhalt

+3

Selbst wenn Sie das tun könnten, was Sie versuchen wollten, wäre der ursprüngliche Inhalt wegen der Referenzzählung weg. Verwenden Sie einfach eine andere Variable als Referenz. – AKHolland

+0

@AKHolland oh, richtig ... ich habe nicht an die Referenzzählung gedacht ... – soger

+1

@AKHolland, Nonsense. Es kann nicht weg sein, wenn es noch zugänglich ist. Wenn das OP das tun könnte, was es versucht (Zugriff auf den ursprünglichen Wert als '$$ x'), dann wäre es ein großer Fehler in Perl, wenn seine Referenzzahl Null erreicht hätte. – ikegami

Antwort

3

Was Sie fragen, ist unmöglich. Eine Variable kann weder eine Referenz noch eine Zeichenfolge enthalten. Sie müssen zwei Variablen verwenden. Damit haben Sie zwei Möglichkeiten.

Speichern Sie die Referenz in eine neue Variable

$ perl -e' 
    use feature qw(say); 
    my $x = "abc"; 
    my $y = \$x; 
    say $y; 
    say $$y; 
' 
SCALAR(0x232a398) 
abc 

Schön und einfach, effizient und keine Verwirrung, was die Variable zu welchem ​​Zeitpunkt enthält.

Der Nachteil dieses Ansatzes ist, dass Verweise auf das Original $x die Änderung nicht sehen. Es ist schwer vorstellbar, dass dies jedoch eine Rolle spielen würde.

Beachten Sie, dass die neue Var könnte auch den gleichen Namen wie der alte haben. Ich empfehle das nicht, da es unnötig verwirrend und fehleranfällig ist.

$ perl -e' 
    use feature qw(say); 
    my $x = "abc"; 
    my $x = \$x; 
    say $x; 
    say $$x; 
' 
SCALAR(0x232a398) 
abc 

Speichern Sie den Wert in einer neuen Variablen

$ perl -e' 
    use feature qw(say); 
    my $x = "abc"; 
    $x = \(my $container = $x); 
    say $x; 
    say $$x; 
' 
SCALAR(0x175cbe0) 
abc 

Der Nachteil dieses Ansatzes ist es beinhaltet die Zeichenfolge zu kopieren. Dies ist jedoch nur bis 5.20 Uhr der Fall. 5.20 führte einen Copy-on-Write-Mechanismus für Strings ein. Das bedeutet, dass das obige nicht die Zeichenfolge in 5.20+ kopiert; Es wird stattdessen nur ein Zeiger kopiert. Beachten Sie, dass beiden Skalare den gleichen Zeichenfolge-Puffer (0x2ac53d0) im folgende Beispiel teilen:

$ perl -MDevel::Peek -e'my $x = "abc"; my $y = $x; Dump($_) for $x, $y;' 2>&1 \ 
    | grep -P '^(?:SV| FLAGS| PV)\b' 
SV = PV(0x2a9f0c0) at 0x2abcdc8 
    FLAGS = (POK,IsCOW,pPOK) 
    PV = 0x2ac53d0 "abc"\0 
SV = PV(0x2a9f150) at 0x2abcde0 
    FLAGS = (POK,IsCOW,pPOK) 
    PV = 0x2ac53d0 "abc"\0 

Während $x = \"$x" wurde als kürzere Version $x = \(my $container = $x); vorgeschlagen, zwingt es stringification und kopiert es die gesamte Zeichenfolge, auch in Versionen von Perl, die COW unterstützen.

1

einen Verweis auf den Wert zuweisen, nicht auf die Variable:

my $string = 'abcefgh'; 
$string = \ "$string"; 

print $$string, "\n"; 
+0

Aber würde das nicht eine Kopie der Saite machen? Würden "abcefgh" und "$ string" nicht gleichzeitig existieren? – soger

+0

@soger: Erstelle es gleich am Anfang: 'my $ string = \ 'abcdefgh';'. – choroba

+1

echtes Leben ist nicht so einfach. – soger