Где находится структура, которая не реализует выделенную копию, и как ее можно вернуть из функции? - PullRequest
0 голосов
/ 04 августа 2020

Я прочитал, что память в Rust по умолчанию выделяется в стеке, если явно не указано компилятору использовать кучу с помощью Box или какого-либо другого метода. между вызовами функций, но где фактически выделена память для структур? Если бы он был в стеке, что произойдет, когда функция завершится?

#[derive(Debug)]
struct Foo(i32);

#[derive(Debug)]
struct Bar(Foo);

fn foo() -> Foo {
    Foo(42)
}

fn bar() -> Bar {
    let f = foo();
    Bar(f)
}

fn main() {
    let bar = bar();
    println!("{:?}", bar);
}

Например, в строке 12 есть структура Foo, выделенная в кадре стека функции bar(). Когда bar() завершается, стек разматывается и память освобождается. Поскольку структура не реализует Copy, память не копируется, так что где это go?

Я думаю, здесь есть фундаментальная идея, которую я не понимаю.

1 Ответ

5 голосов
/ 04 августа 2020

Все 1 каким-то образом хранится в стеке. Даже когда вы выделяете что-то в куче, сам указатель сохраняется в стеке.

Ваши экземпляры Foo и Bar хранятся в стеке. Когда функция возвращает экземпляр, данные перемещаются 2 из внутреннего кадра стека во внешний.

Поскольку структура не реализует Copy, память не копируется

Это не значение признака Copy (выделено мной):

Типы, значения которых могут дублироваться просто копируя биты.

Все 3 в Rust можно перемещать. Если бы это было не так, то языком было бы очень сложно пользоваться! Ваши данные перемещаются из одного кадра стека в другой.

Единственная разница между «копией» и «перемещением» заключается в том, что копия позволяет использовать как исходные, так и целевые значения, а перемещение позволяет использовать только значение назначения, которое будет использоваться.

1 - Практически все. Я ожидал, что static значения на самом деле не хранятся в стеке.

2 - Оптимизатор может фактически удалить ход, выделив структуру в родительский кадр стека , с которого нужно начать, а затем передать указатель дочернему элементу. Это называется оптимизация возвращаемого значения .

3 - Существуют патологические случаи, когда значение нельзя переместить. См. Раздел «Тип со ссылкой на самого себя» в Почему я не могу сохранить значение и ссылку на это значение в одной структуре? .

...