当前位置: 首页 > article >正文

rust学习-所有权

rust学习-所有权

  • 所有权
  • 移动所有权
  • 复制和克隆
  • 引用
  • 可变引用
  • 生命周期
  • 所有权和函数
    • 接受所有权
    • 接受引用
  • 返回值和作用域
  • 注意事项

Rust 的所有权系统是其最大的特色之一,也是 Rust确保内存安全和避免空指针、数据竞争等错误的关键机制,所有权系统的核心概念包括所有权、引用和生命周期

所有权

rust中每个值都有一个与其相关联的变量,称为其所有者,所有权遵循以下规则:

  • 每个值都有一个所有者
  • 值在任何时刻都只能有一个所有者
  • 当所有者离开作用域时,该值将被丢弃
{
    let s = String::from("hello");  // s 进入作用域

    // 使用 s

}  // s 离开作用域,被丢弃

在这个示例中,s 是 String::from(“hello”) 的所有者,当 s 离开作用域时,String 被自动丢弃,释放其占用的内存

移动所有权

当将一个值赋给另一个变量时,所有权会被转移,原始变量不再有效

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // s1 的所有权被转移给 s2

    // println!("{}", s1);  // 这里会报错,因为 s1 已经不再有效
    println!("{}", s2);  // 正确,s2 拥有字符串
}

在这个示例中,s1 的所有权被转移给 s2,因此 s1 在转移后不能再使用

复制和克隆

对于简单数据类型,如整数和布尔值,Rust 会自动复制它们,因此不会发生所有权转移

let x = 5;
let y = x;  // x 被复制,y 也等于 5

对于复杂类型,如 String,需要显式地克隆数据

let s1 = String::from("hello");
let s2 = s1.clone();  // 克隆 s1 的数据

引用

引用可使用变量的值而不转移所有权,引用必须是 immutable(不可变)的,除非显式指定为 mutable(可变)

let s1 = String::from("hello");
let len = calculate_length(&s1);  // 传递引用
println!("The length of '{}' is {}.", s1, len);

fn calculate_length(s: &String) -> usize {
    s.len()
}

在这个示例中,&s1 是一个对 s1 的引用,calculate_length 函数接受一个 &String 参数

可变引用

要修改通过引用传递的值,需要使用可变引用

let mut s = String::from("hello");
change(&mut s);

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

在这个示例中,&mut s 是一个可变引用,允许在 change 函数中修改 s 的值

生命周期

生命周期是 Rust 编译器用于确保引用总是有效的机制,编译器会检查引用的生命周期,确保它们不会超过所引用数据的生命周期

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

在这个示例中,'a 是一个生命周期参数,表示返回的引用至少和传入的引用一样长

所有权和函数

函数可以接受所有权或引用作为参数

接受所有权

fn takes_ownership(some_string: String) {
    // some_string 现在是这个函数的局部变量
    println!("{}", some_string);
}

fn main() {
    let s = String::from("hello");
    takes_ownership(s);
    // s 现在不再有效
}

接受引用

fn calculates_length(s: &String) -> usize {
    s.len()
}

fn main() {
    let s = String::from("hello");
    let length = calculates_length(&s);
    println!("The length of '{}' is {}.", s, length);
}

返回值和作用域

函数可以返回值的所有权

fn gives_ownership() -> String {
    let some_string = String::from("hello");
    some_string  // 返回 some_string 的所有权
}

fn main() {
    let s = gives_ownership();
    println!("{}", s);
}

注意事项

  • 避免悬挂引用:不要返回对局部变量的引用,因为局部变量在函数结束时会被丢弃
fn bad() -> &String {
    let s = String::from("hello");
    &s  // 错误,s 在函数结束时被丢弃
}
  • 不可变引用和可变引用的规则
    • 在同一作用域内,只能有多个不可变引用或一个可变引用
    • 不能在有可变引用的同时有不可变引用
let mut s = String::from("hello");

let r1 = &s;  // 不可变引用
let r2 = &s;  // 另一个不可变引用
// let r3 = &mut s;  // 错误,已有不可变引用

println!("{} and {}", r1, r2);
drop(r1); drop(r2);

let r3 = &mut s;  // 可变引用
println!("{}", r3);
  • 生命周期注解:对于复杂的情况,可能需要显式指定生命周期
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
  • Deref 自动引用转换:Rust 的自动解引用(deref coercions)可以隐式地将引用转换为其他类型的引用
struct Person {
    name: String,
    age: u8,
}

fn print_name(p: &Person) {
    println!("Name: {}", p.name);
}

fn main() {
    let person = Person { name: String::from("Alice"), age: 30 };
    print_name(&person);
}

http://www.kler.cn/a/519560.html

相关文章:

  • 关于MySQL InnoDB存储引擎的一些认识
  • python 变量范围的定义与用法
  • VB6.0 显示越南语字符
  • 医疗集群系统中基于超融合数据库架构的应用与前景探析
  • 云原生:构建现代化应用的基石
  • MySQL数据库笔记——版本号机制和CAS(Compare And Swap)
  • MongoDB使用详解
  • 【多视图学习】Self-Weighted Contrastive Fusion for Deep Multi-View Clustering
  • 无人机如何自主侦察?UEAVAD:基于视觉的无人机主动目标探测与导航数据集
  • 记录备战第十六届蓝桥杯的过程
  • JVM堆空间
  • 图像处理之HSV颜色空间
  • 【第七天】零基础入门刷题Python-算法篇-数据结构与算法的介绍-一种常见的分治算法(持续更新)
  • Brightness Controller-源码记录
  • 独立开发者常见开发的应用有哪些
  • 正则表达式基础与应用
  • 第22篇:Python开发进阶:详解使用SQLAlchemy进行ORM数据库编程技术
  • OpenEuler学习笔记(八):安装OpenEuler
  • 14-6-3C++STL的list
  • 如何使用群晖NAS配置MySQL与phpMyAdmin远程管理
  • 商业航天更青睐哪些芯片
  • 网易Android开发面试题200道及参考答案 (下)
  • 长短期记忆网络LSTM
  • python爬虫入门(一) - requests库与re库,一个简单的爬虫程序
  • Kubernetes可视化界面
  • three.js+WebGL踩坑经验合集(3):THREE.Line的射线检测问题(不是阈值方面的,也不是难选中的问题)