# 栈和堆

the-stack-and-the-heap.md
commit 049b9e4e8067b998e4581d026b0bc6d1113ab9f5

## 栈

fn main() {
let x = 42;
}

fn foo() {
let y = 5;
let z = 100;
}

fn main() {
let x = 42;

foo();
}

0 x 42

foo()被调用，一个新的栈帧被分配：

2 z 100
1 y 5
0 x 42

foo()结束后，它的帧被释放：

0 x 42

fn italic() {
let i = 6;
}

fn bold() {
let a = 5;
let b = 100;
let c = 1;

italic();
}

fn main() {
let x = 42;

bold();
}

0 x 42

3 c 1
2 b 100
1 a 5
0 x 42

4 i 6
3 c 1
2 b 100
1 a 5
0 x 42

italic()结束后，它的帧被释放，只留下bold()main()

3 c 1
2 b 100
1 a 5
0 x 42

0 x 42

## 堆

fn main() {
let x = Box::new(5);
let y = 42;
}

1 y 42
0 x ??????

(230) - 1 5
... ... ...
1 y 42
0 x → (230) - 1

(230) - 1 5
(230) - 2
(230) - 3
(230) - 4 42
... ... ...
3 y → (230) - 4
2 y 42
1 y 42
0 x → (230) - 1

1 y 42
0 x ??????

## 参数和借用

fn foo(i: &i32) {
let z = 42;
}

fn main() {
let x = 5;
let y = &x;

foo(y);
}

1 y → 0
0 x 5

x是一个普通的5，而y是一个指向x的引用。所以它的值是x的所在内存位置，它在这是0

3 z 42
2 i → 0
1 y → 0
0 x 5

## 一个复杂的例子

fn foo(x: &i32) {
let y = 10;
let z = &y;

baz(z);
bar(x, z);
}

fn bar(a: &i32, b: &i32) {
let c = 5;
let d = Box::new(5);
let e = &d;

baz(e);
}

fn baz(f: &i32) {
let g = 100;
}

fn main() {
let h = 3;
let i = Box::new(20);
let j = &h;

foo(j);
}

(230) - 1 20
... ... ...
2 j → 0
1 i → (230) - 1
0 h 3

(230) - 1 20
... ... ...
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

xyz分配了空间。参数xj有相同的值，因为这是我们传递给它的。它是一个指向0地址的指针，因为j指向h

(230) - 1 20
... ... ...
7 g 100
6 f → 4
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

(230) - 1 20
... ... ...
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

(230) - 1 20
(230) - 2 5
... ... ...
10 e → 9
9 d → (230) - 2
8 c 5
7 b → 4
6 a → 0
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

bar()的末尾，它调用了baz()

(230) - 1 20
(230) - 2 5
... ... ...
12 g 100
11 f → (230) - 2
10 e → 9
9 d → (230) - 2
8 c 5
7 b → 4
6 a → 0
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

baz()结束后，我们移除了fg

(230) - 1 20
(230) - 2 5
... ... ...
10 e → 9
9 d → (230) - 2
8 c 5
7 b → 4
6 a → 0
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

(230) - 1 20
... ... ...
5 z → 4
4 y 10
3 x → 0
2 j → 0
1 i → (230) - 1
0 h 3

(230) - 1 20
... ... ...
2 j → 0
1 i → (230) - 1
0 h 3

## 该用啥？（Which to use?）

### 语义影响（Semantic impact）

1. Gigabyte可以表示两个意思：109 或 230。SI（国际单位制）标准解释为“gigabyte”是 109， 而“gibibyte”是 230。然而，很少有人用这个术语，而依赖语境上下文来区别。这里我们遵循传统。

2. 我们可以通过转移所有权来让内存活的更久，这有时叫做“移出箱子”。我们将在后面涉及更复杂的例子。