Stavo cercando di capire come si comportano le strutture quando vengono restituite dai metodi. C'è una sezione nella sezione nightly della "Ruggine Book" Detto questo, se si è utilizzato la sintassi ...I valori nella posizione di ritorno vengono sempre assegnati nel frame dello stack dei genitori o nella casella di ricezione?
let x = box i_return_a_struct();
.. che non ci sarebbe stata una copia, quindi non v'è alcuna necessità di restituire un puntatore. Ma quando ho iniziato a giocare con esso, sembra che lo box
non sia necessario, a meno che non sia necessario che il valore esista nell'heap.
#[derive(Debug)]
struct Dummy {
data: i64,
}
impl Drop for Dummy {
fn drop(&mut self) {
println!("{:?} is going out of scope", self as *const Dummy);
}
}
fn make_dummy(i: i64) -> Dummy {
Dummy { data: i }
}
fn main() {
{
let i = 15i32;
println!("{:?} is a variable on the stack frame", &i as *const i32);
let dummy1 = make_dummy(1);
println!("{:?} was returned and is being used", &dummy1 as *const Dummy);
let dummy2 = make_dummy(2);
println!("{:?} was returned and is being used", &dummy2 as *const Dummy);
let dummy3 = Box::new(make_dummy(3));
println!("{:?} box was returned and is being used", &(*dummy3) as *const Dummy);
let dummy4 = Box::new(make_dummy(4));
println!("{:?} box was returned and is being used", &(*dummy4) as *const Dummy);
}
println!("Leaving main");
}
uscita:
0x23fb94 is a variable on the stack frame
0x23faf8 was returned and is being used
0x23fa50 was returned and is being used
0x2825030 box was returned and is being used
0x2825040 box was returned and is being used
0x2825040 is going out of scope
0x2825030 is going out of scope
0x23fa50 is going out of scope
0x23faf8 is going out of scope
Leaving main
fare valori/le strutture in posizione di ritorno sempre vengono assegnati nei genitori pila telaio o la ricezione di scatola?
MODIFICA: PS - c'è qualche indicazione nei documenti per quanto riguarda quando si verificherà l'elisione della copia in generale?
EDIT: Oltre la soluzione accettata, la seguente Q + A era illuminante: What are move semantics exactly? Chiarito molti punti per me.
Non c'è magia, la copia ellis è comune, si verifica già in molti compilatori C e C++. Questo è il motivo per cui ho collegato un gestore di Drop al mio oggetto, come mi aspetterei di vederlo scoppiare 2 volte per ogni chiamata se si verificava una copia.A meno che non mi sbagli, copia elision succede sempre nell'esempio nel mio post. –
Voglio solo chiarire: 'Box :: new()' non è la sintassi "vecchia". In realtà è una funzione aggiunta per rendere possibile la creazione di un 'Box' su stable mentre la sintassi' box' è configurata. Se/quando 'box' viene stabilizzato,' Box :: new() 'probabilmente andrà via, o rimarrà semplicemente come un altro modo per ottenere un' Box'. –
@RichHenry Se si verificava una copia, il compilatore si sarebbe lamentato del fatto che 'Dummy' non implementasse la caratteristica' Copia '. In caso di 'Box :: new (make_dummy (3))' il valore viene spostato (nel senso di trasferimento di proprietà) nella casella non copiata, quindi non si vedono i registri di drop aggiuntivi. Inoltre, 'Box :: new' è semplicemente una funzione che il compilatore non è in grado di ottimizzare il modo in cui ho descritto sopra, quindi ci sono ancora tutti gli elementi in movimento dallo stack allo heap. – eulerdisk