2015-04-03 13 views
29

Ci sono diverse domande che sembrano riguardare lo stesso problema che sto avendo. Ad esempio, vedere here e here. Fondamentalmente sto cercando di creare un String in una funzione locale, ma poi restituirlo come &str. La tranciatura non funziona perché la durata è troppo breve. Non riesco ad utilizzare str direttamente nella funzione perché ho bisogno di costruirlo dinamicamente. Tuttavia, preferirei anche non restituire un valore String poiché la natura dell'oggetto in cui si trova è statica una volta creata. C'è un modo per avere la mia torta e mangiarla anche tu?Restituisce stringa locale come slice (& str)

Ecco un minimo riproduzione non compilazione:

fn return_str<'a>() -> &'a str { 
    let mut string = "".to_string(); 

    for i in 0..10 { 
     string.push_str("ACTG"); 
    } 

    &string[..] 
} 
+3

Altre domande hanno lo stesso problema, e la risposta è sempre la stesso: non è possibile costruire un 'String' in una funzione e restituirlo come' & str' a causa del modello di memoria Rust. – Levans

+1

Il tuo ragionamento per non voler restituire una stringa non ha senso per me. Basta memorizzare un 'String' in questo oggetto" statico "invece di un' & str'. È più facile, è almeno ergonomico, ha più senso per la proprietà e non ha nemmeno un vantaggio in termini di prestazioni. – delnan

+0

@delnan In realtà hai risposto qualcos'altro di cui mi stavo chiedendo, ovvero se l'uso di '' String'' ha degli svantaggi in termini di prestazioni. Dovrei essere in grado di ridefinire l'uso di '' String''s – anderspitman

risposta

47

No, non può farlo. Ci sono almeno due spiegazioni perché è così.

Innanzitutto, ricorda che i riferimenti sono presi in prestito, cioè indicano alcuni dati ma non li possiedono, sono di proprietà di qualcun altro. In questo caso particolare, la stringa, una sezione a cui si desidera tornare, è di proprietà della funzione perché è memorizzata in una variabile locale.

Quando la funzione termina, tutte le sue variabili locali vengono distrutte; ciò comporta chiamare i distruttori e il distruttore di String libera la memoria utilizzata dalla stringa. Tuttavia, si desidera restituire un riferimento preso in prestito che punta ai dati allocati per quella stringa. Significa che il riferimento restituito diventa immediatamente pendente - punta a una memoria non valida!

La ruggine è stata creata, tra le altre cose, per prevenire tali problemi. Pertanto, in Rust è impossibile restituire un riferimento che punta in variabili locali della funzione, che è possibile in linguaggi come C.

C'è anche un'altra spiegazione, leggermente più formale. Diamo un'occhiata a vostra firma funzione:

fn return_str<'a>() -> &'a str 

Ricordate che tutta la vita e parametri generici sono, beh, parametri: sono impostati dal chiamante della funzione. Per esempio, qualche altra funzione può chiamare in questo modo:

let s: &'static str = return_str(); 

Questo richiede 'a essere 'static, ma è ovviamente impossibile - la funzione non restituisce un riferimento ad una memoria statica, restituisce un riferimento con una vita strettamente inferiore. Pertanto, tale definizione di funzione non è corretta ed è vietata dal compilatore.

In ogni caso, in tali situazioni è necessario restituire un valore di un tipo di proprietà, in questo caso particolare sarà una proprietà String:

fn return_str() -> String { 
    let mut string = String::new(); 

    for _ in 0..10 { 
     string.push_str("ACTG"); 
    } 

    string 
} 
+2

Tecnicamente è possibile restituire un 'String' come' 'statico' purché si verifichi la stringa 'String'. (Con 'std :: mem :: forget'), ma rimarrà assegnato per sempre. (Che immagino il punto in "statico") –