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 并移出给调用的函数

}

最后修改:2024 年 05 月 05 日
如果觉得我的文章对你有用,请随意赞赏