Rust 所有权 简介

文章目录

  • 发现宝藏
  • 1. 所有权基本概念
  • 2. 所有权规则
  • 3. 变量作用域
  • 4. 栈与堆
    • 4.1 栈(Stack)
    • 4.2 堆(Heap)
  • 5. String类型
    • 5.1 String 类型
    • 5.2 String 的内存分配
    • 5.3 所有权与内存管理
    • 5.4 String 与切片
  • 6. 变量与数据交互方式
    • 6.1 移动(Move)
    • 6.2. 克隆(Clone)
  • 7. 所有权与函数
    • 7.1. 传递参数
    • 7.2. 返回值
  • 总结

发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。


所有权(系统)是 Rust 最为与众不同的特性,它让 Rust 无需垃圾回收(garbage collector)即可保障内存安全。因此,理解 Rust 中所有权如何工作是十分重要的。我们将讲到所有权以及相关功能:借用、slice 以及 Rust 如何在内存中布局数据。

1. 所有权基本概念

所有权(ownership)是Rust的核心特性之一,它确保了内存安全,避免了内存泄漏等问题。每个值在Rust中都有一个所有者,即一个变量。每个值只能有一个所有者,当所有者离开作用域时,这个值将被自动丢弃。

2. 所有权规则

首先,让我们看一下所有权的规则。当我们通过举例说明时,请谨记这些规则:

  • Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
  • 值有且只有一个所有者。
  • 当所有者(变量)离开作用域,这个值将被丢弃。

3. 变量作用域

在Rust中,变量的作用域是指变量在程序中有效的范围。当变量离开作用域时,其所有权的值将被自动清理。例如:

let s = "hello";
{
    let s = String::from("hello");
    // 使用 s
} // 此作用域已结束,s 不再有效

好的,让我们详细探讨 Rust 中的栈(Stack)与堆(Heap)存储,以及如何与所有权机制关联。

4. 栈与堆

在 Rust 中,数据可以存储在两种主要的内存区域:栈(Stack)和堆(Heap)。这两种存储方式各自具有不同的特性和用途。

4.1 栈(Stack)

栈是一种具有后进先出(LIFO)特性的内存结构。在栈上分配内存的过程非常高效,因为栈的内存分配和释放只涉及到栈顶指针的简单移动。

4.1.1 特点

  1. 固定大小:栈上存储的数据必须具有固定大小。在编译时,编译器知道数据的确切大小,因此可以在栈上进行高效的内存管理。
  2. 自动管理:栈上的数据在作用域结束时自动释放。这意味着栈上存储的局部变量会在其作用域结束时立即被销毁,栈指针会自动回退。
  3. 有限大小:栈的大小通常较小,超出栈的大小限制会导致栈溢出错误(Stack Overflow)。

4.1.2 示例

fn main() {
    let x = 42; // 整型数据存储在栈上
    let y = 3.14; // 浮点型数据存储在栈上
    let z = 'a'; // 字符型数据存储在栈上
}

在这个例子中,xyz 都是固定大小的数据,它们会被分配在栈上。

4.2 堆(Heap)

堆是一种具有动态分配特性的内存区域,用于存储大小不固定的数据。堆上的内存分配不像栈那样高效,但它适用于需要动态内存管理的情况。

4.2.1 特点

  1. 动态大小:堆上的数据可以具有动态大小。你可以在运行时分配任意大小的内存,这使得堆非常适合存储不确定大小的数据。
  2. 手动管理:在 Rust 中,堆上的内存管理是自动的,由所有权机制管理。堆上的数据会在所有者超出作用域时自动释放。
  3. 可扩展:与栈相比,堆的大小受限较少,可以分配较大的内存块。

4.2.2 示例

fn main() {
    let s = String::from("Hello"); // 字符串在堆上分配内存
}

在这个例子中,String 是一个在堆上分配内存的动态数据结构。它的内存分配不再是固定的,而是由 String 类型内部的堆分配机制来处理。

5. String类型

以String类型为例,它存储在堆上,可以存储在编译时未知大小的文本。当我们创建一个String类型的变量时,实际上是在堆上分配了一块内存。

5.1 String 类型

在 Rust 中,String 是一个动态字符串类型,它与 &str(字符串切片)不同。String 提供了可变的、可增长的字符串,可以在运行时修改其内容,并支持复杂的字符串操作。与 &str 不同的是,String 的内存分配是在堆上进行的。

5.1.1 String 的结构

String 类型的内部结构包括以下几个部分:

  • 指针(Pointer):指向堆上实际存储字符串数据的位置。
  • 长度(Length):当前字符串的字符数(字节数)。
  • 容量(Capacity):堆上分配的总内存量,以字节为单位,通常比实际长度要大,以支持字符串的增长。

这个结构允许 String 具备动态扩展的能力,能够在需要时增长。

5.2 String 的内存分配

当你创建一个 String 实例时,Rust 会在堆上分配足够的内存来存储字符串数据。以下是 String 内存分配的关键步骤:

5.2.1 创建 String

fn main() {
    let s = String::from("Hello, world!"); // 创建一个新的 String
}
  1. 分配内存:Rust 会在堆上分配一块内存来存储字符串数据。在这个过程中,String 会分配比实际需要的更多的内存,以便在未来的操作中能够容纳更多的字符。这种预分配机制有助于减少频繁的内存分配开销。

  2. 存储数据:字符串数据(例如 "Hello, world!")会被复制到堆上的内存中。此时,String 的指针指向堆上这块内存的起始位置。

  3. 更新元数据String 会维护内部的长度和容量信息。长度是当前存储的字符数,而容量是分配的总字节数。这样,Rust 可以有效管理字符串的增长和缩减。

5.2.2 动态增长

当你向 String 中添加更多字符时,Rust 会根据需要动态调整内存分配:

fn main() {
    let mut s = String::from("Hello");
    s.push_str(", world!"); // 动态增长
}
  1. 检查容量String 首先检查当前容量是否足够容纳新增的字符。如果足够,则直接在现有内存中追加字符。

  2. 重新分配:如果当前容量不足以容纳新数据,String 会重新分配更大的堆内存,通常是原来容量的两倍。然后将旧数据复制到新分配的内存中,更新指针,最后释放旧内存。

5.3 所有权与内存管理

String 的内存管理由 Rust 的所有权系统自动处理,确保了内存的安全性和有效性:

  • 所有权转移:当 String 的所有权转移到另一个变量时,堆上的数据也会随之转移,避免了数据的重复释放或访问无效内存的问题。

    fn main() {
        let s1 = String::from("Hello");
        let s2 = s1; // s2 现在拥有堆上的数据
        // println!("{}", s1); // 错误!s1 不再是有效的所有者
        println!("{}", s2); // 正确!s2 是有效的所有者
    }
    
  • 自动释放:当 String 的所有者超出作用域时,Rust 会自动调用 String 的析构函数,释放堆上的内存。这防止了内存泄漏和资源泄漏。

    fn main() {
        {
            let s = String::from("Hello");
            // 使用 s
        } // s 超出作用域,堆内存被释放
    }
    

5.4 String 与切片

虽然 String 是一个动态可变的字符串,但其内部可以借用不可变的字符串切片 &str。这种方式允许在不拥有数据所有权的情况下安全地访问字符串的一部分:

fn main() {
    let s = String::from("Hello, world!");
    let slice: &str = &s[0..5]; // 切片借用字符串的一部分
    println!("{}", slice); // 输出 "Hello"
}

String 类型在 Rust 中提供了强大的动态字符串操作能力。它通过在堆上分配内存来支持可变长度的字符串,并利用 Rust 的所有权系统自动管理内存。了解 String 的内存分配和管理机制能够帮助你更好地编写高效、安全的 Rust 代码。

6. 变量与数据交互方式

6.1 移动(Move)

当将一个变量赋值给另一个变量时,Rust默认会进行移动操作,而非深拷贝。这意味着,原始变量的所有权会转移给新变量,原始变量将不再有效。

 let s1 = String::from("hello");
 let s2 = s1; // s1 的所有权移动到 s2    

6.2. 克隆(Clone)

如果我们需要深拷贝堆上的数据,可以使用clone方法。

 let s1 = String::from("hello");
 let s2 = s1.clone(); // s2 是 s1 的深拷贝

7. 所有权与函数

7.1. 传递参数

将值传递给函数时,所有权会转移。如果函数参数是Copy类型的,则会进行拷贝;否则,会进行移动。

 fn takes_ownership(some_string: String) {
     println!("{}", some_string);
 }
 fn makes_copy(some_integer: i32) {
     println!("{}", some_integer);
 }

7.2. 返回值

函数的返回值也可以转移所有权。通过返回值,我们可以将函数内部创建的值的所有权传递给外部。

 fn gives_ownership() -> String {
     let some_string = String::from("hello");
     some_string
 }
 fn takes_and_gives_back(a_string: String) -> String {
     a_string
 }

总结

所有权是Rust语言的核心特性之一,它为内存管理提供了全新的解决方案。掌握所有权机制,有助于我们编写更安全、高效的Rust代码。虽然所有权概念在初学者看来较为复杂,但只要勤加练习,相信大家都能熟练运用。在后续的学习中,我们将继续探讨Rust的其他高级特性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/879217.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第二期: 第11节, uboot 命令的使用

问题:如果你只想控制一个led 灯,并且不想去写驱动。 那么可以直接 使用uboot 的命令,去改写内存。 uboot 命令的解析: 读命令, md[.b, .w. .l] address 注意: 这里的 .w 指的是两个字节,…

探索Python的Excel世界:openpyxl的魔法之旅

文章目录 探索Python的Excel世界:openpyxl的魔法之旅背景:为什么选择openpyxl?什么是openpyxl?如何安装openpyxl?简单的库函数使用方法场景应用:openpyxl在实际工作中的应用常见bug及解决方案总结 探索Pyth…

Spring高手之路23——AOP触发机制与代理逻辑的执行

文章目录 1. 从整体视角学习Bean是如何被AOP代理的2. AOP代理的触发机制2.1 postProcessAfterInitialization方法源码分析2.2 wrapIfNecessary方法源码分析2.3 时序图演示触发机制 3. AOP代理逻辑的执行3.1 AOP代理如何使用拦截器3.2 proceed方法源码分析3.3 时序图 1. 从整体视…

特价电影票对接接口平台推荐?微客云影票

特价电影票对接接口平台推荐 一、常见的较好平台 微客云影票与全国 12000 多家影院建立了合作,覆盖范围广,其提供的电影票价格普遍低于市场价,平均每张票能省下不少钱,在万达、CGV 等大型影院优惠更为显著。 二、判断平台好坏的…

【Qt】Qt C++ Widget中嵌入qml

1. 效果 2. 方法 使用QQuickWidget方式 QQuickWidget *view new QQuickWidget;view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));view->show();除了QQuickWidget方式还可以使用QQuickView方式,请自行查阅资料 3. 代码 3.1 工程目录 3.2 …

Weblogic部署

要安装weblogic,首先要有java环境,因此需要先安装jdk。 这里需要注意,weblogic版本不同,对应的jdk版本也不同,我在这里就踩了很多坑,我这里下载的是fmw_12.2.1.4.0_wls_lite_generic.jar对应的是jdk-8u333…

visual prompt tuning和visual instruction tuning

visual prompt tuning:作为一种微调手段,其目的是节省参数量,训练时需要优化的参数量小。 输入:视觉信息image token可学习的prompt token 处理任务:比如常见的分类任务 visual prompt tuning visual instruction tu…

唯徳知识产权管理系统 DownloadFileWordTemplate 文件读取漏洞复现

0x01 产品简介 唯徳知识产权管理系统,由深圳市唯德科创信息有限公司精心打造,旨在为企业及代理机构提供全方位、高效、安全的知识产权管理解决方案。该系统集成了专利、商标、版权等知识产权的全面管理功能,并通过云平台实现远程在线办公,提升工作效率。是一款集知识产权申…

客户说了算!精益产品开发,让中小企业精准触达用户需求!——张驰咨询

随着全球经济环境的波动,特别是疫情后经济复苏进程的反复,很多中小制造企业面临产品滞销、同质化严重和内卷竞争加剧的困境。市场饱和、利润微薄,还在新产品开发上遇到了研发人才不足、资金短缺等问题。许多企业在这场市场博弈中徘徊在生死边…

IP协议及相关特性

IP协议负责地址管理和路由选择。它的组成为: 接下来我们将对其中较重要的部分进行介绍。 4位版本:这里的四位版本只有两个取值 分别为IPv4和IPv6,这两个额分别为不同的IP协议,但是现在主流的还是IPv4但是近年来IPv6在中国的普及率…

关于报表新入职及进阶培训入口教程

关于报表新入职及进阶培训入口教程 一、网站二、登陆三、报名入口四、缴费及注意事项1. 报名2. 注意事项 五、学习1.在首页时,可以点个人中心进入学习。2.进入后,可以进入如下步骤。 六、完 一、网站 教育事业统计在线培训 二、登陆 注:如果…

C++速通LeetCode简单第17题-爬楼梯(全网最简单)

思路要点:将问题转化为求斐波那契数列的第n项,然后迭代。 思路分析:最后一次爬的阶数不是1就是2,假设爬n阶的方法数是f(n),假设最后一次爬1阶,那么爬前面的 n-1阶的方法数是f(n-1);假设最后一次…

20240911泰山杯初赛--temp

Wireshark打开temp.pcap流量包,发现有很多ICMP协议包。 一些ICMP数据包较大,且可发现,明显在传输HTTP协议数据内容: 右键,【显示分组字节】,进一步分析这些HTTP数据: GET /test.html HTTP/1.…

C盘清理不能偷懒!用这方法快速清理10G以上垃圾 操作简单又安全

C盘清理不能偷懒!用这方法快速清理10G以上垃圾 操作简单又安全。到现在为止,还有很多的人不知道怎么清理C盘,主要是因为Windows操作系统相对复杂,其文件管理和存储结构对于非专业人士来说可能难以理解。许多用户可能不清楚哪些文件…

重磅!WOS、Scopus数据库相继更新,多本期刊被剔除(附下载)

关注GZH【欧亚科睿学术】,一键获取最新期刊目录列表 节后首天,科睿唯安及爱思唯尔相继更新了数据库,小编给大家总结了各数据库的期刊变动情况,供大家参考。详情如下: 01 SCIE/SSCI目录更新 2024年9月17日&#xff0c…

计算机毕业设计公交站点线路查询网站登录注册搜索站点线路车次/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序

选题背景‌: 随着城市化进程的加快,公共交通成为城市居民出行的重要方式。然而,传统的公交站点线路查询方式往往依赖于纸质地图或简单的电子显示屏,查询效率低下且信息更新不及时。因此,开发一个功能全面、易于使用的…

【SQL】百题计划:SQL对于空值的比较判断。

[SQL]百题计划 方法&#xff1a; 使用 <> (!) 和 IS NULL [Accepted] 想法 有的人也许会非常直观地想到如下解法。 SELECT name FROM customer WHERE referee_Id <> 2;然而&#xff0c;这个查询只会返回一个结果&#xff1a;Zach&#xff0c;尽管事实上有 4 个…

MAGDA:多智能体指南驱动的诊断助手

MAGDA&#xff1a;多智能体指南驱动的诊断助手 秒懂大纲提出背景精细拆解输入输出全流程创意视角中文意译 论文&#xff1a;MAGDA: Multi-agent guideline-driven diagnostic assistance 秒懂大纲 ├── MAGDA: Multi-agent guideline-driven diagnostic assistance【研究主…

DockerLinux安装DockerDocker基础

Linux软件安装 yum命令安装 通过yum命令安装软件,是直接把软件安装到Linux系统中 安装和卸载都比较麻烦,因为软件和系统是强关联的 Docker docker是一种容器技术,可以解决软件和系统强关联关系,使得软件的安装和卸载更方便,它可以将我们的应用以及依赖进行打包,制作出一个镜…

教程 | ArcGIS Pro如何自动保存数据编辑内容

目录 1、工程自动保存 2、数据编辑自动保存 世界上最痛苦的事情就是&#xff1a; 软件崩溃&#xff0c;我没保存&#xff01;&#xff01;&#xff01; 电脑死机&#xff0c;我没保存&#xff01;&#xff01;&#xff01; 突然断电&#xff0c;我没保存&#xff01;&…