title: 所有权
updated: 2023-12-14T23:15:06.0000000+08:00
created: 2023-11-27T21:17:44.0000000+08:00
Rust没有类似GC的内存回收机制
Rust定义可变的字符串类型:
pub fn syq(){
let mut <u>s</u> = String::from("这是");
<u>s</u>.<u>push_str</u>("syq函数");
println!("{}",<u>s</u>);
}
为了支持可变性,一般来说没有GC的语言需要在堆(heap)上分配内存,且需要在不使用的时候手动返回
Rust采用的方式不同,当值的变量不在自己的作用范围时,内存就会立即返还给系统,以上面代码为例子,s的作用范围(作用域)只是syq函数内,一旦执行程序执行完这个函数,就会立即将内存还给系统(执行完函数时会调用drop这个函数)
Rust中每一个值都被一个变量拥有,该变量被称为值的所有者。
一个值只能被一个变量所拥有。
虽然rust强调所有权,但有些类型的变量可以直接复制,这是rust的一个叫做copy的特性:
fn main() {
let s1:i32 = 2;
let s2: i32 = s1;
println!("{},{}, world!", s1,s2);
}
比如这段代码,像整数这样的值是基本类型,在编译的时候已知大小,会被存储在栈上,所以这里会直接copy而不会报所有权的错。
这种类型还包括:
- 所有整数类型,比如u32
- 布尔类型,bool,它的值是true和false
- 所有浮点数类型,比如f64
- 字符类型,char
- 元组,当且仅当其包含的类型也都是Copy的时候。比如,(i32, i32)是Copy的,但(i32, String)就不是
- 不可变引用&T,但是注意: 可变引用&mut T是不可以 Copy的 (转移所有权中有例子)
那如果我们就是想要把不可以直接复制的给复制出来呢?
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
这段代码中,使用了clone(),使s2完整复制了s1的数据,这就是克隆,现在你有两个值相同的变量,但不建议常用这种方法,只在有必要的时候(比如初始化程序等待期,或者短时间只会执行一次时)使用,因为它会大幅度降低软件性能
函数也会产生所有权的问题,结合作用域会有一些需要注意的地方
fn main() {
let s = String::from("hello"); // s 进入作用域
takes_ownership(s); // s 的值移动到函数里 ...
// ... 所以到这里不再有效
let x = 5; // x 进入作用域
makes_copy(x); // x 应该移动函数里,
// 但 i32 是 Copy 的,所以在后面可继续使用 x
} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走,
// 所以不会有特殊操作
fn takes_ownership(some_string: String) { // some_string 进入作用域
println!("{}", some_string);
} // 这里,some_string 移出作用域并调用 \`drop\` 方法。占用的内存被释放
fn makes_copy(some_integer: i32) { // some_integer 进入作用域
println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作
函数的返回值也会有所有权:
fn main() {
let s1 = gives_ownership(); // gives_ownership 将返回值
// 移给 s1
let s2 = String::from("hello"); // s2 进入作用域
let s3 = takes_and_gives_back(s2); // s2 被移动到
// takes_and_gives_back 中,
// 它也将返回值移给 s3
} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走,
// 所以什么也不会发生。s1 移出作用域并被丢弃
fn gives_ownership() -\> String { // gives_ownership 将返回值移动给
// 调用它的函数
let some_string = String::from("hello"); // some_string 进入作用域.
some_string // 返回 some_string 并移出给调用的函数
}
// takes_and_gives_back 将传入字符串并返回该值
fn takes_and_gives_back(a_string: String) -\> String { // a_string 进入作用域
a_string // 返回 a_string 并移出给调用的函数
}
仅登录用户可评论,点击 登录