【Rust 中级教程】 15 引用与借用(3)

简介: 【Rust 中级教程】 15 引用与借用(3)

0x00 开篇


本篇文章将继续介绍 Rust 的引用。本篇文章将介绍引用作为函数/方法参数和返回值的一些用法,以及注意事项。由于函数/方法用法相同,所以本文示例代码将以函数为主。本篇文章的阅读时间大约 5 分钟。


0x01 引用作为函数/方法参数


当我们在传递非 Copy 标记的类型的参数时,往往会失去所有权。如果我们在执行某个函数或者方法时,不想失去所有权,我们可以定义引用参数传给函数/方法。

fn main() {
    let mut a = String::from("hello");
    print_string(&a);
    // 向 a 中追加字符串
    a.push_str(" rust!");
    print_string(&a);
    println!("println! 打印--- {}", a);
}
// 打印一个字符串
fn print_string(s: &String) {
    println!("print_string 打印--- {}", s);
}

我们创建了一个 print_string 函数,接收的参数是引用类型的。然后声明字符串变量 a, 将 a 的引用传入该函数。即使在后面再次使用 a ,它也不会失去所有权。当引用离开作用域时,将会归还所有权。

另外,值得注意的一点是 当进行解引用时,将会重新获得所有权。

下面的操作是错误的!!!!!!!!!!!!!

fn main() {
    let aa = String::from("xxx");    operate_string(&aa);}
fn operate_string(aa: &String) {
    // 下面的代码是错误的    // let x = *aa;}

上面的操作是错误的!!!!!!!!!!!!!

“当一个函数/方法接收引用时,我们在函数/方法内对参数解引用。” 假设这种做法是可行的,aa 的所有权被转移给 x, 那么函数/方法执行结束后,x销毁失去所有权,外部的 aa 将指向未知的位置,aa 将会变成野指针。所以此做法是被禁止的,编译将会发生错误。


0x02 引用作为函数/方法返回值


同样的,引用还可以作为函数/方法的返回值来使用。

fn main() {
    let mut b = String::from("hello world");    let c = get_self(&mut b);    println!("c = {}", c);}
fn get_self(s: &String) -> &String {
    return s;}
// 运行结果
// c = hello world


上面仅仅是一个很简单的例子,我们将在后面的 lifetime 章节中详细介绍。


0x03 胖指针 (Fat Pointer)


我们前面介绍的引用都是对一个值比较简单的引用,引用的仅仅是一个地址。胖指针也是一种引用,但是它包含两部分

  • 某个值的地址
  • 使用该值的相关必要信息

Rust 胖指针有两种,切片(slice)和特型对象(trait object)。切片通常包含切片地址和长度信息,如最常见的 &str。对于特型对象,是对实现某种特型的一个值的引用。特型对象包含某个值的地址和一个指向与该值匹配的特型实现的指针。PS:我即将在后面章节中介绍。


普通引用和胖指针的区别


普通引用与胖指针唯一的区别就是**胖指针携带了额外的信息,占用两个字节的内存。**其它的没有区别,都可以是可以修改的或者共享的,都不拥有自己指向的值,它们的 lifetime 都不能超出目标的值。

0a2653c851af460fa595bd959398a8f1.png


0x04 小结


本篇文章介绍的知识点比较简单,主要了解下胖指针的概念就可以了。如果你了解 C++ ,那么你会发现,目前所介绍的引用与 C++ 非常像,但又有 Rust 的特点。下一篇文章将介绍 Rust 的新概念 lifetime

相关文章
|
6月前
|
Rust 安全 编译器
Rust中的生命周期与借用检查器:内存安全的守护神
本文深入探讨了Rust编程语言中生命周期与借用检查器的概念及其工作原理。Rust通过这些机制,在编译时确保了内存安全,避免了数据竞争和悬挂指针等常见问题。我们将详细解释生命周期如何管理数据的存活期,以及借用检查器如何确保数据的独占或共享访问,从而在不牺牲性能的前提下,为开发者提供了强大的内存安全保障。
|
6月前
|
设计模式 Rust JavaScript
【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
86 0
|
4月前
|
Rust
rust 引用了Trait的实现,为什么还需要引入Trait 才能调用实现的方法
rust 引用了Trait的实现,为什么还需要引入Trait 才能调用实现的方法
|
5月前
|
Rust 安全 开发者
Rust引用、借用和所有权详解
Rust引用、借用和所有权详解
|
6月前
|
Rust 编译器
【Rust】——函数(所有权)以及借用或引用
【Rust】——函数(所有权)以及借用或引用
|
6月前
|
Rust 安全 编译器
Rust中避免常见错误:悬挂引用与生命周期不匹配
本文深入探讨了Rust编程语言中常见的两个内存管理错误:悬挂引用和生命周期不匹配,并提供了避免这些错误的实用方法。我们将详细解释这两种错误的来源,并通过示例展示如何在Rust中通过正确的生命周期标注和借用规则来避免它们,从而确保代码的内存安全性。
|
6月前
|
存储 Rust 安全
Rust 中的引用与借用
Rust 中的引用与借用
|
Rust 安全 编译器
Rust 基础入门 —— 2.3.所有权和借用 (二)
同一时刻,你只能拥有要么一个可变引用, 要么任意多个不可变引用 引用必须总是有效的 贴一个体验不错的学习链接恰饭:学习链接
86 0
|
存储 Rust 安全
Rust 基础入门 —— 2.3.所有权和借用
写在前面的序言 因为我们这里实际讲述的内容是关于 内存安全的,所以我们最好先复习一下内存的知识。
51 0
|
Rust 安全 JavaScript
Rust教程初识
当然,它们都有编译然后执行可执行程序的用法。应当有编译后改名的方式,不然那也太不coooooooooooool了。
78 0