rust学习------[day2]理解ownership的特性

本文介绍了Rust编程语言中的所有权概念,包括变量如何通过move和clone与数据交互。所有权系统确保了内存安全,避免了数据复制的性能问题。move操作不会深拷贝数据,而clone则会。栈上的数据如整型等类型默认深拷贝。Rust函数参数传递遵循所有权规则,值会被移动到函数内部,若需继续使用需通过返回值。此外,文章还讨论了函数返回值与作用域的关系。
摘要由CSDN通过智能技术生成

Ownership

变量和数据的交互方式:move

普通变量的赋值

fn main() {
    let x = 5;
    let y = x;
}

第一句将5与变量x绑定,第二句是创建了一个x的值的副本,并将该值与变量y绑定

String类型变量的赋值

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;
}

在rust中一个String类型由三部分组成:

  • 指向保存字符串内容的内存(这块内存在堆上)的指针
  • 长度
  • 容量

所以,上面的代码在rust中的处理可能有以下情况

  • 堆上的字符串内容并没有复制,仅复制栈上的变量,然后将s2的指针也指向堆上的字符串内容

    在这里插入图片描述

  • 堆和栈的内容都进行复制

    在这里插入图片描述

    这两种做法都有很大的缺点,方法一在变量失效的时候会多次释放内存,导致出错。方法二在字符串很大的时候程序的执行效率很差。所以rust采用的是下面的方式

  • 在方案一的基础上,s2复制完后,就将s1视为失效,s1超出范围之后不释放内存

    在这里插入图片描述

变量和数据的交互方式:clone

上面提到的move型的操作是不会对数据进行深拷贝,仅仅拷贝变量然后移交控制权。接下来介绍的clone型操作方式是会对数据进行深拷贝的

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();

    println!("s1 = {}, s2 = {}", s1, s2);
}

这段代码的执行就如方法二所示

栈上的数据

在复制时都是深拷贝。原因是:诸如在编译时具有已知大小的整数之类的类型完全存储在堆栈中,因此可以快速制作实际值的副本。

rust中可以给类型实现Copy trait,这样我们新实现的类型就可以放置在栈空间中。但是我们不能给已经实现了drop trait的类型再实现Copy trait。

不需要分配操作的类型都可以实现Copy trait。

以下是一些具有Copy trait的类型:

  • 所有的整型,类似u32
  • 布尔型
  • 所有的浮点型,类似f64
  • 字符类型,char
  • Tuples(元组中的类型只包含具有Copy trait的类型)

Ownership和函数

给函数传值类似于赋值操作,举个例子

fn main() {
    let s = String::from("hello");  // s comes into scope

    takes_ownership(s);             // s's value moves into the function...
                                    // ... and so is no longer valid here

    let x = 5;                      // x comes into scope

    makes_copy(x);                  // x would move into the function,
                                    // but i32 is Copy, so it's okay to still
                                    // use x afterward

} // Here, x goes out of scope, then s. But because s's value was moved, nothing
  // special happens.

fn takes_ownership(some_string: String) { // some_string comes into scope
    println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing
  // memory is freed.

fn makes_copy(some_integer: i32) { // some_integer comes into scope
    println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.

当将s传入take_ownership函数之后,在使用变量s就会出错

返回值和Scope

直接举例

fn main() {
    let s1 = gives_ownership();         // gives_ownership moves its return
                                        // value into s1

    let s2 = String::from("hello");     // s2 comes into scope

    let s3 = takes_and_gives_back(s2);  // s2 is moved into
                                        // takes_and_gives_back, which also
                                        // moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
  // moved, so nothing happens. s1 goes out of scope and is dropped.

fn gives_ownership() -> String {             // gives_ownership will move its
                                             // return value into the function
                                             // that calls it

    let some_string = String::from("hello"); // some_string comes into scope

    some_string                              // some_string is returned and
                                             // moves out to the calling
                                             // function
}

// takes_and_gives_back will take a String and return one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
                                                      // scope

    a_string  // a_string is returned and moves out to the calling function
}

如果我们希望将变量传入函数之后继续使用该变量,我们需要将值以返回值的形式在返回给变量。如果想返回多个值,可以以元组的形式将值返回

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值