fn main() {
println!("{}", "所有权");
// ① 所有权机制 所有权是rust的核心功能,让rust无需实行垃圾回收机制就可以保证内存安全
// 1. 每个变量都有一个被称为所有者(对这个变量的内存空间层删改查)
// 2. 每个变量每一个时刻只有一个所有者
// 3. 当所有者离开作用域,这个变量将被丢弃
// 4. 基本类型存储在栈上 没有所有者的概念(相当于每次赋值,传值,返回值,都是新的值)
// 5. 每次赋值,传值,返回值 都会转移所有权
let a = 10;
let b = a;
println!("{}", a);
println!("{}", b);
let str1 = String::from("张三");
let str2 = str1;
// println!("{}", str1);// 报错 参考上面第四条,str1的所有权转移给str2了
// let str2 = &str1; // 引用
// let str2 = str1.clone(); // 克隆一份出来 不支持 copy()
// copy 只针对 基本数据类型(只会复制栈上的值),clone() 都针对(会把栈和堆上的数据一起复制)
// println!("{}", str1);
println!("{}", str2);
// ②引用 和 借用
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
// 直接返回 所有权,不过又要赋值新变量名 不是很方便
// fn sum_vec(v1: Vec<i32>, v2: Vec<i32>) -> (i32, Vec<i32>, Vec<i32>) {
// let sum1: i32 = v1.iter().sum();
// let sum2: i32 = v2.iter().sum();
// (sum1 + sum2, v1, v2)
// }
// 引用
fn sum_vec(v1: &Vec<i32>, v2: &Vec<i32>) -> (i32) {
let sum1: i32 = v1.iter().sum();
let sum2: i32 = v2.iter().sum();
(sum1 + sum2)
}
let (answer) = sum_vec(&vec1, &vec2);
println!("{}--{:?}--{:?}", answer, vec1, vec2);
println!("{}", format!("{}/{}", 1, 2));
// 引用写个 &mut
let mut vmut = vec![1, 10, 20, 30];
fn push_vec(v: &mut Vec<i32>, value: i32) {
println!("{}", v.is_empty());
println!("{:?}--{:?}", v.len(), v.get(v.len() - 1));
// unwrap() 取Some(3) 值的 必须确保 some存在不然会报错 所以先判断v 是否为空
if v.is_empty() || v.get(v.len() - 1).unwrap() < &value {
v.push(value)
}
v.push(value)
}
push_vec(&mut vmut, 10);
println!("{:?}----mut", vmut);
// 借用
// 1. 在同一个作用域只能有 一个可变引用,和多个不可变引用
// 2. 在可变引用释放前 不能访问资源所有者(貌似所以引用都是这样不能访问所有者)
// 3. 任何引用的作用域都必须小于资源所有者的作用域,并离开作用域后自动释放(资源所以者都消失了,引用还有啥用 哈哈哈)
let mut x = 6;
let y = &mut x;
// let z = &x; //不满足 第一条
// println!("{}--{}", y,x); // 不满足第二条
println!("{}", y);
// 切片 是针对 数组,字符串...
// 切片后就变成 &str 类型的了(本来字符串是 string类型 切片就变 &str了)
let s = String::from("hello,rust");
println!("{}", &s[0..5]);//hello
println!("{}", &s[5..]);//,rust
println!("{}", &s[0..]);//hello,rust
fn print_str(s: &str) {
println!("{}--{}", s.len(), s)
}
print_str(&s[0..2]);
print_str(&s[0..]);
let mut veccc = vec![1, 2, 3, 4, 5];
let qvec = &mut veccc[0..3];
qvec[0] = 100;
// veccc.into_iter(); // 转移所有权迭代器 在访问 veccc 就会报错
// veccc.iter(); // 不可变迭代器
// veccc.iter_mut();// 可变迭代器
for i in veccc.iter_mut() {
println!("{:p}", i); // 这个i在这里是地址 需要* 取值才行
*i += 100
}
println!("{:?}-**-*-*-", veccc);
// ③生命周期
// 1. 每一个引用已经包含引用的数据结构 都有一个作用域这个作用域就是生命周期
// 2. 生命周期是隐式推断的,特殊情况下需要自己写
// 定义生命周期:&'a i32 ,&'a mut i32,&'a str
// 隐式生命周期
fn foos(x: &str) -> &str {
x
}
fn foo<'a>(x: &'a str) -> &'a str {
x
}
// 显示生命周期
// 编译报错,rust不知道如何处理,
// x rust推断出是 'a
// y rust推断出是 'b
// 你返回的生命周期没办法推断是 'a / 'b
// fn long_str(x: &str, y: &str) -> &str {
// if x.len() > y.len() {
// x
// } else {
// y
// }
// }
fn long_str<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
// 静态生命周期 ,他是具有和整个程序运行的生命周期相同的生命周期
// 'static 字符串字面量默认就是这种,所以推荐使用String类型的
let str = "站事";
// 悬垂指针就是 指针引用的无效的数据
let str1 = String::from("abcd");
let result;
{
let str2 = "xyz";
result = long_str(str1.as_str(), str2)
}
println!("{}", result);
// 1. 每一个省略的生命周期注解的参数,都具有不相同的生命周期,
// fn foo(x:&i32) => fn foo<'a>(x:&'a i32)
// fn foo(x:&i32,y:&i32) => fn foo<'a,'b>(x:&'a i32,y:&'b i32)
// 2. 如果只有一个输入生命周期,这个生命周期会复制给所以省略的生命周期
// fn foo(x:&i32)->&i32 => fn foo<'a>(x:&'a i32)->&'a i32
// 3. 方法中的self发生命周期会赋值给所以省略的输出的生命周期
struct aa<'a> {
x: &'a i32,
}
}
发表评论