//所有权
//这是Rust最为与众不同的特性,它让Rust无需garbage collector,即刻保障内存安全
/*一般程序使用计算机内存的方式*/
//1.垃圾回收机制:在程序运行时不断寻找不再使用的内存
//2.程序员亲自分配和释放内存
//3.Rust:通过所有权系统管理内存,编译器在编译时进行检查
/*堆和栈*/
//在Rust这样的系统编程语言中,值位于栈还是堆上会影响语言的行为
//栈:先进后出,增加数据:进栈,移除数据:出栈,栈上所有数据必须时已知且固定的大小
//堆:在编译时未知大小和大小可能变化的数据存在堆上,堆是缺乏组织的
//堆上分配内存或分配:内存分配器在堆的某处找到足够大的空位,标记为已使用,并返回该位置地址的指针
//入栈比堆上分配快:入栈不需要搜索内存空间,其位置总是在栈顶.
//访问堆比访问栈慢:堆必须通过指针访问,而现代处理器在内存中跳转越少越快
//调用函数的过程:当你的代码调用一个函数时,传递给函数的值(包括可能指向堆上数据的指针)和函数的局部变量被压入栈中。当函数结束时,这些值被移出栈。
/*所有权做的事情*/
//1.跟踪哪部分代码正在使用堆上的数据
//2.减少堆上重复数据的数量
//3.清理堆上不再使用的数据
//4.有了以上这些,就不需要考虑堆和栈了
/*所有权规则*/
// 1.Rust 中的每一个值都有一个被称为其所有者(owner)的变量。
// 2.值在任一时刻有且只有一个所有者。
// 3.当所有者(变量)离开作用域,这个值将被丢弃。
/*变量作用域*/
//变量从声明的点开始直到当前作用域结束时都是有效的
// { // s 在这里无效, 它尚未声明
// let s = "hello"; // 从此处起,s 是有效的
// // 使用 s
// } // 此作用域已结束,s 不再有效
/*String类型*/
//字符串字面值:即被硬编码进程序里的字符串值,但它是不可变的
//String:这个类型管理被分配到堆上的数据,所以能够存储在编译时未知大小的文本
//::是运算符,允许将from函数置与String类型的命名空间下
// let s = String::from("hello");
/*字符串字面值和String在内存与分配上的不同*/
// 字面值:因为编译时就知道内容所以文本直接硬编码进最终的可执行文件,所以快速而又高效,得益于字符串字面值的不可变性
// String:为了支持可变,可增长的文本片段,要在堆上分配一块编译时未知大小的内存来存放内容,
// String:这意味着1.只有在运行时向memory allocator请求内存,2.还要有一个处理完String时
// String:将内存返回给分配器的方法
/*Rust处理返回内存的方法*/
//内存在它离开作用域后自动释放,Rust会在结尾的"}"处调用一个叫drop的特殊函数
// {
// let s = String::from("hello"); // 从此处起,s 是有效的
//
// // 使用 s
// } // 此作用域已结束,
// // s 不再有效
//资源获取即初始化(Resource Acquisition Is Initialization(RAII)):在C++中,item在生命
//周期结束时释放资源的模式,这个模式对编写Rust代码有这深远的影响
/*变量与数据互动方式1:移动*/
// let s1 = String::from("hello");
// let s2 = s1;
//内存图:https://kaisery.github.io/trpl-zh-cn/img/trpl04-02.svg
//String的底层:一个指向存放字符串内容内存的指针,一个长度,和一个容量
//原理:当s1赋值给s2时,意味着从栈上拷贝了它的指针,长度,容量,并没有复制堆上的数据
//二次释放:当 s2 和 s1 离开作用域,他们都会尝试释放相同的内存,二次释放会导致内存污染
//Rust解决二次释放的方法:在 let s2 = s1 之后,Rust 认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西。
//移动:以上s1无效,s2有效叫做移动,而非浅拷贝或深拷贝
//隐藏的设计:Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何自动的复制可以被认为对运行时性能影响较小。
fn main() {
}