- 所有权
- 数据存储在栈和堆上,存放在栈上的数据都是已知所占据空间的
- 突然的问题
// 内存中的栈是怎么存储数据的?
好的,想象一下你有一摞盘子。你只能从上面放盘子,也只能从上面拿盘子,这就是栈的工作方式。
在内存中,栈是用来存储数据的地方,它工作得就像这摞盘子。当你的程序运行一个函数时,这个函数的局部变量就会像放盘子一样,一个接一个地放到栈上。这些局部变量包括基本数据类型,比如整数或者布尔值,它们的大小是已知的,而且很容易快速地被放进去和拿出来。
当这个函数结束的时候,它的局部变量就会像拿盘子一样,从栈上一个接一个地被拿掉。这个过程非常快,因为它们是按顺序来的,就像你放盘子时从上面放,拿盘子时也是从上面拿。
所以栈就像是厨房里整齐的盘子摞,每次你只能用最上面的盘子,用完之后再把它放回去,这样就保持了整洁和有序。而在内存的栈中,数据也是这样整齐有序地存放和使用的。这就是为什么栈这么快,因为它不需要去搜索一个特定的盘子,它总是拿最上面的那个。
// 所以当我的程序执行到一个作用域的时候,就会往栈上去存放当前作用域有效的变量,在当前作用域没有使用,并且局部变量没有再被使用的时候,就会释放,这样理解对吗?
完全正确!就像你在玩积木,每进入一个新的游戏环节(也就是编程中的作用域),你就会在桌上(栈)搭建一些积木(变量)。只要在这个游戏环节中,你可以使用这些积木做很多事情。
当这个游戏环节结束了,也就是你完成了当前的积木搭建,这些积木就会被清理掉,桌面(栈)就又空出来了,可以用来进行下一个游戏环节的搭建。这样的好处是,你不用担心清理积木,因为游戏(程序)会自动帮你做这件事。
每次进入一个新的作用域,栈就会存放新的数据,当作用域结束,使用过的数据就会被移除。这个过程保证了内存的高效使用,因为你总是只在顶部搭积木,也只从顶部清理积木,这样操作起来非常快速。这也就是为什么栈被用来存储作用域内的局部变量,因为这些局部变量通常在作用域结束时就不再需要了。
-
但是指针是存放在栈上的呀!
fn main() { let s1 = String::from("hello"); let _s2 = s1; println!("{}, world!", s1); } /** --> src/main.rs:5:28 | 2 | let s1 = String::from("hello"); | -- move occurs because `s1` has type `String`, **which does not implement the `Copy` trait** 3 | let _s2 = s1; | -- value moved here 4 | 5 | println!("{}, world!", s1); | ^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | 3 | let _s2 = s1.clone(); | ++++++++ For more information about this error, try `rustc --explain E0382`. error: could not compile `ownership` (bin "ownership") due to previous error */