Что происходит в памяти, когда право собственности передается из коробки? - PullRequest
3 голосов
/ 07 января 2020

Переменная s в print_struct относится к данным в куче или в стеке?

struct Structure {
    x: f64,
    y: u32,
    /* Use a box, so that Structure isn't copy */
    z: Box<char>,
}

fn main() {
    let my_struct_boxed = Box::new(Structure {
        x: 2.0,
        y: 325,
        z: Box::new('b'),
    });
    let my_struct_unboxed = *my_struct_boxed;
    print_struct(my_struct_unboxed);
}

fn print_struct(s: Structure) {
    println!("{} {} {}", s.x, s.y, s.z);
}

Насколько я понимаю, let my_struct_unboxed = *my_struct_boxed; переводит владельца из коробки в my_struct_unboxed, а затем в s в функции print_struct.

Что происходит с фактическими данными? Первоначально он копируется из стека в кучу путем вызова Box::new(...), но являются ли данные каким-то образом перемещенными или скопированными обратно в стек в какой-то момент? Если так, то как? А когда drop называется? Когда s выходит из области видимости?

Ответы [ 2 ]

3 голосов
/ 07 января 2020

Данные Structure в my_struct_boxed существуют в куче, а данные Structure в my_struct_unboxed существуют в стеке.

Поэтому наивно говоря (без оптимизации компилятора ), операция перемещения или копирования при разыменовании (*) вашего Box всегда будет включать копирование данных. Что касается анализа заимствования / анализа c, поскольку признак Copy не реализован для Structure, это означает передачу права собственности на данные в переменную my_struct_unboxed.

Когда вы вызываете print_struct, происходит другая копия, которая будет копировать биты в памяти, представляющие ваш Structure из локальной переменной, в стек вызовов аргументов функции. Семантически, это снова представляет передачу права собственности на функцию print_struct.

Наконец, когда print_struct выходит из области видимости, он отбрасывает принадлежащий ему Structure.


Ссылка: std::marker::Copy

Отрывок

Важно отметить, что в этих двух примерах единственное различие заключается в том, разрешен ли вам доступ к [вашему переменная] после назначения. Под капотом и копирование, и перемещение могут привести к копированию битов в памяти, хотя иногда это оптимизируется.

Обратите внимание на последнюю часть: «иногда это оптимизируется». Вот почему более ранние описания были упрощены, чтобы не предполагать оптимизацию компилятора, т.е. наивно. Во многих случаях компилятор будет активно оптимизировать и вставлять код, особенно с более высокими значениями для флага opt-level.

2 голосов
/ 07 января 2020

Если да, то как?

И "копировать", и "двигать" семантически memcpy (хотя это может быть оптимизировано для чего-то другого, или даже вообще ничего).

А когда называется drop? Когда s выходит из области видимости?

Да. Когда print_struct заканчивается, он очищает локальную область видимости и сбрасывает s.

...