共计 2039 个字符,预计需要花费 6 分钟才能阅读完成。
所有权
先看一段代码
let s3 = "hello";
let s4 = s3;
println!("{}", s3);
let s1 = String::from("hello");
let s2 = s1;
//println!("{}", s1); //Error:^^ value borrowed here after move
let array1 = [0,1,2,3,4,5];
let ap = &array1;
println!("{}", ap[3])
println!("{:p},{:p}", &array1, ap);
打印 s3 的能够失常执行,打印 s1 的却报错。这是什么起因?
<1>s3 的内容是栈里调配的, s3 = s4 这是 copy 操作,相似复制了一个字符类型的变量 s4.
如下类型的会是 copy 类型的。因为这些类型都是在栈里调配的,所以应用 copy 操作会很快
- 所有整数类型
- 布尔
- 浮点
- 字符(是字符,不是 string!!)
- 元组(元组内的元素也都是 copy 类型的,(i32, i32), (i32, ‘aa’) 是 copy 类型。(i32,String) 的不是 copy 类型
<2>s1 是 String, 不是字符类型。的内容是在堆里调配的,s2 = s1 的操作是将 s1 指向内存 ”hello” 的所有权转移给 s2. 所以 s1 就被开释了
<3> 借用操作符 &, 这与 C /C++ 相似,就是应用 & 获取内存地址。ap = &array1 理论就是获取 array1 的内存地址,付给 ap.
所有权与函数
-
函数参数所有权
函数会有参数传入,此时所有权是否会产生变更?
测试代码如下U32FnGetOwner
let v:u32 = 32; println!("v address before fn:{:p}", &v); getU32Owner(v); println!("v address after fn:{:p}", &v); println!("{}", v) fn getU32Owner(v:u32) {println!("v address in fn:{:p}", &v); println!("v value:{}", v); }
失常执行
栈上调配的 copy 类型的变量,在函数内 copy 出新的变量。输入后果如下:v address before fn:0x7ff7bbc7a30c v address in fn:0x7ff7bbc798e4 v value:32 v address after fn:0x7ff7bbc7a30c 32
能够看到,在函数外和函数内,地址不同
StringFnGetOwner
let str1 = String::from("String owner"); getOwner(str1); println!("{}", str1); //Error:^^^^ value borrowed here after move fn getStringOwner(s:String) {println!("Show s:{}",s); }
会提醒错误信息,无奈编译通过
堆上调配的变量,当在函数内产生所有权变更,传入函数变量的所有权也会变更str1 曾经产生所有权变更,无奈再应用
这就引起了一个问题,传入参数所有权都产生了变更,函数后就无奈应用了。如果想持续应用传入参数该如何做?答案是通过援用的形式,对于援用,学过 C /C++ 的应该都很分明了
let mut str4 = String::from("Beautiful"); let (str5, l) = refStr(&mut str4); println!("{}", str4); println!("{}, len:{}", str5, l); fn refStr(s: &mut String) -> (String, usize) {s.push_str("sky"); (s.to_string(), s.len()) }
输入后果如下
Beautiful sky Beautiful sky, len:13
通过援用,在函数内可能操作 str4 的内容(变量定义时以及函数参数定义处的 mut 很重要,否则无奈在函数内变更内容),同时函数返回 str4 的所有权没有产生变更。
援用
对于援用学过 C /C++ 的应该都比拟相熟,对于 rust 来说对于援用有以下几点须要留神
<1> 可变援用只能有一个,不可变援用能够有多个。可变援用只能有一个的起因就是为了防止数据竞争,当有多个可变援用就会有数据竞争的可能。
let mut ss = String::from("FFFF");
let rr1 = &mut ss;
let rr2 = &mut ss; //Error:cannot borrow `ss` as mutable more than once at a time
println!("{}, {}", rr1, rr2)
<2> 不能即存在可变援用又存在不可变援用
let mut ss = String::from("FFFF");
let rr1 = &ss;
let rr2 = &mut ss; //Error:cannot borrow `ss` as mutable because it is also borrowed as immutable
println!("{}, {}", rr1, rr2)