2015-01-23 12 views
7

Ich habe folgenden Code und wissen nicht, wie es zum Laufen zu bringen:Wie initialisiert man eine Variable mit einer Lebensdauer?

fn new_int<'a>() -> &'a isize { 
    &5 
} 

fn main() { 
    let x = new_int(); 
} 

Oder einen neuen Versuch:

fn new_int<'a>() -> &'a isize { 
    let a: &'a isize = &5; 
    a 
} 

fn main() { 
    let x = new_int(); 
} 
+1

Ich weiß nicht, was Sie tun möchten, aber was Sie tun, versucht, einen Verweis auf einen Wert zu erstellen, dessen Lebensdauer kleiner als 'a ist. Es hat die Lebensdauer des Körpers der Funktion. –

+0

Ich versuche, diese Variable außerhalb des Körpers mit lebenslangen Parameter zu belichten. Wenn es möglich ist. – Hinogary

+1

Diese Variable ist außerhalb des Funktionskörpers leer. Wenn Sie darauf zugreifen könnten, würden Sie anderen Speicher überschreiben. Die Fehlermeldung (siehe http://is.gd/ju7hFZ) sagt Ihnen genau das. –

Antwort

9

Sie können nicht. Mit einem Parameter für die Lebensdauer können Sie nicht festlegen, wie lange ein Wert beibehalten wird. Sie können nur dem Compiler mitteilen, dass zwei oder mehr Referenzen mit demselben Speicher "verwandt" sind und dieselbe Lebensdauer erwarten.

Eine Funktion (wie new_int in Ihrem Fall) kann den Speicher auf zwei Arten zuordnen:

  • lokal in einem Bereich (der Stapel), die die Funktion zugeordnet ist, selbst und zerstört wird, wenn Sie aus der Funktion zurückkehren
  • dynamisch in einem Bereich des Speichers, der zu allen Funktionen gemeinsam ist (oft als „Haufen“ bezeichnet, obwohl dies nicht in allen Fällen nicht mehr notwendigerweise korrekt ist)

Referenz (&) a po Inter zu einem Bereich des Gedächtnisses. Es kann auf den lokalen Stapel oder auf den "Heap" zeigen. Da dynamische Zuordnungen in Bezug auf die Leistung wesentlich teurer sind als das Schreiben auf dem Stapel, verwendet Rust standardmäßig den Stapel (Sie müssen eine Box verwenden, um eine dynamische Zuordnung durchzuführen).

Also, kurz gesagt, das ist, warum Ihr Code illegal ist:

fn new_int<'a>() -> &'a isize { 
    let a: &'a isize = &5; // write 5 on the local stack 
    a // return a pointer to that area of memory 
} // the area of memory where I wrote 5 is destroyed here, 
    // so the pointer I'm trying to return is not valid 

Sie entweder den Wert

fn new_int() -> isize { 
    5 
} 

fn main() { 
    let a = new_int(); // the value 5 (not a pointer) is copied into a 
} 

oder führen eine dynamische Zuordnung zurückgeben kann (was viel des Guten im Fall von ein isize, aber könnte sinnvoll sein, wenn Sie tatsächlich mit einer großen Struktur arbeiten)

alternativ y, Sie können Speicher außerhalb der Funktion zuordnen und in der Funktion mutieren. Sie tun nicht in der Regel es für einen primitiven Typ, aber es macht Sinn in einigen Szenarien (zB Streaming von Daten):

// new_int does not return anything. Instead it mutates 
// the old_int in place 
fn new_int(old_int: &mut isize) { 
    *old_int = 5; 
} 

fn main() { 
    let mut a = 2; // memory for an int is allocated locally 
        // in main() 
    new_int(&mut a); // a mutable reference to that memory is passed 
        // to new_int, that overwrites it with another value 
} 

Als @dk mentions in the comment below,, in diesem speziellen Fall (dh Ihre Funktion gibt immer 5 oder eine andere statisch bekannte Wert, nicht etwas dynamisch durch die Funktion berechnet) Sie auch eine Referenz mit einer 'static Lebensdauer zurückkehren können:

fn new_int<'a>() -> &'a isize { 
    static FIVE: isize = 5; 
    &FIVE 
} 

Sie können in the Rust Reference mehr über 'static lesen.

Ab Rust 1.21 wird diese "statische Werbung" automatisch für Sie durchgeführt und Ihr ursprünglicher Code wird kompiliert. Es erzeugt das Äquivalent des static FIVE.

+4

Verwerfen meiner eigenen laufenden Antwort, aber ich möchte auf eine dritte Option hinweisen: Wenn es * immer * 5 zurückgibt, oder irgendeine endliche Menge von Antworten, können Sie eine geliehene Referenz auf eine statische Variable zurückgeben: 'static FIVE : isize = 5; ', dann' & FIVE' als Ergebnis der Funktion. –

5

Eine alternative Art und Weise zu verstehen, warum ist

fn new_int<'a>() -> &'a isize { 
    &5 
} 

kann nicht funktionieren wie folgt.'a ist eine Lebensdauer Parameter der Funktion; das heißt, es ist der Aufrufer wer wählt den tatsächlichen Wert dieses Parameters, nicht die Funktion selbst. Zum Beispiel kann der Anrufer 'static Lebensdauer wählen:

let i: &'static isize = new_int(); 

jedoch &5 nicht die 'static Lebensdauer, so dass die Funktion abgelehnt wird haben können.

Mit anderen Worten sagt eine solche Erklärung im Wesentlichen: "Ich kann Ihnen eine Referenz von jedem Leben geben, das Sie wollen". Dies ist natürlich nur dann gültig, wenn die von der Funktion zurückgegebene Referenz die 'static Lebensdauer hat, die die größtmögliche Lebensdauer darstellt. Das ist was DK. erzählt übrigens.

Verwandte Themen