目录
所有权
栈内存stack 堆内存heap
- stack 后进先出
- 所有存储在stack上的数据必须拥有已知的固定的大小
- 编译时大小未知的数据或者运行时大小可能发生变化的数据必须存放在heap上
- heap的内存组织差一些
-
数据放入heap时,会请求一定数量的空间
-
操作系统在heap中找到一块足够大的空间,把它标记为在用,并返回一个指针,也就是这个空间的地址
- 指针是已知固定大小的,可以把指针存放在stack上
- 访问stack的数据比heap快的多
- 把数据压到stack比在heap上分配快得多
所有权存在的原因
- 跟踪代码的哪些部分正在使用heap的哪些数据
- 最小化heap上的重复数据量
- 清理heap上未使用的数据以避免空间不足
- 管理heap数据就是所有权存在的原因
所有权规则
1 每个值都有一个变量,这个变量就是值得所有者
2 每个值同时只能有一个所有者
3 当所有者超出作用域时,该值将被删除
变量作用域 (同c)
String类型
- 可以使用from函数从字符串字面值创建出string类型
- let s= String::from(“hello”);
- 为什么string类型可以修改,字符串字面值不能修改
- 因为内存处理方式不同
- strig:为了支持可变性,需要在heap上分配内存来保存编译时未知的文本
变量和数据交互的方式:移动 move
多个变量可以与同一个数据使用一种独特的方式来交互
- 为了保证内存安全
- rust没有尝试复制被分配的内存
- rust让s1失效
- 当s1离开作用域的时候,rust不需要释放任何东西
### 变量和数据交互的方式:克隆 clone
针对heap上的数据,stack上直接赋值就是复制
变量和数据交互的方式:复制 copy
所有权与函数
let s=String::from(("llll"));
take_ownerhip(s);//失效
let n=3;
make_copy(n);//n仍然有效
那如何只使用值呢?
引用与借用
参数的类型是&String
&符号表示引用:允许使用某些值而不获得所有权
let s=String::from(("llll"));
take_ownerhip(&s);//不会失效
引用类型的变量默认不可修改
加mut可以可以修改
在同一块作用域内,变量只能有一个可变的引用
不可以同时拥有一个可变的引用和不可变得引用
多个不可变的引用是可以的
悬空引用
fn main() { let r=dangle(); } fn dangle()->&String(){ let s=String::from("heello"); &s }
错误 dangle被执行完后,s已经无效
切片
Rust的另外一种不持有所有权的数据类型:切片(slice)
字符串切片
- 字符串切片是指向字符串的一部分内容的引用
- 【开始索引…结束索引】
- 开始索引是切片起始位置的索引值
- 结束索引是切片终止位置的下一个索引值
let str=String::from("Hello world");
let x=&str[0..6];
let y=&str[..];
println!("{},{}",x,y);
输出Hello ,Hello world
输出字符串中空格前的内容 ,若没有空格则输出全部
字符串字面值是切片
字符串字面值被直接存储在二进制程序当中
let s=“hello” 不可变
将字符串切片作为参数传递
其他类型的切片
let a=[1,2,3,4,5];
let slice=a[0..2];