Day2用 rustlings 练习 Rust 语言-Move Semantics

news2024/11/26 16:26:38

大家好

今天 完成 2024年自动驾驶OS开发训练营-初阶营第四期-导学

Day2用 rustlings 练习 Rust 语言 -Move Semantics

alt
alt
alt

https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html

提交代码时候 提示 没有权限怎么出来

alt
alt

aciton

alt

参考开发环境配置

https://rcore-os.cn/arceos-tutorial-book/ch01-02.html

我的题目

https://github.com/cicvedu/rustlings-semester-4-watchpoints

创建ssh key,用于ssh方式克隆github代码。 在linux环境下,使用ssh-keygen -t rsa -b 4096 -C "你的邮箱"命令,创建ssh key, 下面的选项全部直接敲回车即可。 随后使用 cat ~/.ssh/id_rsa.pub

Primitive Types

Rust has a couple of basic types that are directly implemented into the compiler. In this section, we'll go through the most important ones.

Further information

  • Data Types
  • The Slice Type
alt

The Slice Type Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.

A slice is a kind of reference, so it does not have ownership.

alt
alt

在 Rust 中,切片(slice)是从数组或另一个切片中引用一系列连续元素的视图。要创建一个切片,你需要指定切片的开始和结束位置(不包含结束位置的索引)。在数组 a 中,如果你想得到 [2, 3, 4] 这个切片,你需要从索引 1 开始,到索引 4 结束(不包含索引 4)。

下面是如何修复你的测试代码:

#[test]
fn slice_out_of_array() {
    let a = [12345];

    // 从索引 1 开始,到索引 4 结束的切片
    let nice_slice = &a[1..4];

    assert_eq!([234], nice_slice);
}

在这个例子中,&a[1..4] 创建了一个从数组 a 中索引 1 开始到索引 3 结束的切片,因为 Rust 的切片语法是左闭右开区间(包含开始,不包含结束)。这样 nice_slice 就包含了数组 a 中的 [2, 3, 4]

在命令行输入rustlings watch 开始编辑代码的循环实验

alt

Understanding Ownership

Ownership is Rust’s most unique feature and has deep implications for the rest of the language.

It enables Rust to make memory safety guarantees without needing a garbage collecto

What Is Ownership?

alt

Ownership Rules First, let’s take a look at the ownership rules. Keep these rules in mind as we work through the examples that illustrate them:

  • Each value in Rust has an owner.
  • There can only be one owner at a time.
  • When the owner goes out of scope, the value will be dropped

alt
alt

代码示例本身是正确的,并且展示了 Rust 中所有权和复制的概念。但是,如果您想要确保代码能够编译并运行,并且想要满足一些可能的改进或更正,这里有一些建议:

  1. 确保 takes_ownershipmakes_copy 函数在 main 函数之前定义,因为 Rust 中的函数需要先声明后使用。

  2. 添加注释,说明为什么 stakes_ownership 调用后不能被使用,而 xmakes_copy 调用后仍然可以被使用。

  3. 添加 main 函数的返回类型,虽然在简单的程序中这不是必需的,但这是一个好的编程习惯。

  4. 使用 Rust 的格式化工具,比如 rustfmt,来保持代码的整洁。

下面是根据上述建议修改后的代码:

fn takes_ownership(some_string: String) { // 函数定义在 main 之前
    println!("{}", some_string);
// some_string 的作用域结束,调用 Drop

fn makes_copy(some_integer: i32) { // 函数定义在 main 之前
    println!("{}", some_integer);
// some_integer 的作用域结束,没有调用 Drop,因为 i32 是 Copy 类型

fn main() -> () { // 明确 main 函数的返回类型为 ()
    let s = String::from("hello");  // s 拥有 "hello" 的所有权

    takes_ownership(s);             // s 的值移动到 takes_ownership 函数

    // 下面的代码尝试使用 s 将会导致编译错误,因为 s 的值已经移动
    // let len = s.len(); // 错误:s 已移动

    let x = 5;                      // x 包含值 5

    makes_copy(x);                  // x 的值被复制到 makes_copy 函数
                                    // x 仍然有效,因为 i32 是 Copy 类型

    // x 仍然可以使用
    println!("x is {}", x);
}

在这个修改后的版本中,我们添加了 main 函数的返回类型 (),这表示 main 函数不返回任何值。同时,注释被添加来解释为什么 stakes_ownership 调用后不能被使用,而 xmakes_copy 调用后仍然有效。此外,我们还展示了尝试在 takes_ownership 调用后使用 s 会导致编译错误的例子,以及 xmakes_copy 调用后仍然可以使用的例子。

Vectors

Vectors are one of the most-used Rust data structures.

In other programminglanguages, they'd simply be called Arrays, but since Rust operates on a bit of a lower level, an array in Rust is stored on the stack (meaning it can't grow or shrink, and the size needs to be known at compile time), and a Vector is stored in the heap (where these restrictions do not apply).

Vectors are a bit of a later chapter in the book, but we think that they're useful enough to talk about them a bit earlier. We shall be talking about the other useful data structure, hash maps, later.

Further information

  • Storing Lists of Values with Vectors
  • iter_mut
  • map

alt vec_map 函数的作用是接受一个 Vec<i32> 类型的引用(即一个包含 32 位整数的向量),然后返回一个新的 Vec<i32>,这个新向量中的每个元素都是原向量中对应元素的两倍。

具体来说,vec_map 函数中的 mapcollect 方法是这样工作的:

  1. **v.iter()**:这个方法创建了一个迭代器,它遍历 v 向量的每个元素。iter 方法返回的迭代器提供的是向量中元素的不可变引用。

  2. **.map(|element| { element * 2 })**:map 方法接受一个闭包(匿名函数),在这个例子中,闭包接受一个参数 element(向量中的一个元素的不可变引用),然后返回这个元素值乘以 2 的结果。闭包体内的操作 element * 2 实际上是在对引用指向的数据进行解引用(通过 * 操作符)并执行乘法操作。

  3. **.collect()**:map 方法返回的是一个惰性迭代器,它逐个应用闭包中的操作,但不会立即收集结果。collect 方法被调用来将这些经过 map 处理的元素收集到一个新的 Vec<i32> 向量中。

使用 mapcollect 的好处是,它们允许你以一种声明性的方式对集合中的每个元素执行操作,并将结果收集到新的集合中,而不需要编写显式的循环。这种方式代码更简洁,也更符合 Rust 的风格。

这里是一个如何使用 vec_map 函数的示例:

fn main() {
    let original_vec = vec![1234];
    let doubled_vec = vec_map(&original_vec);
    println!("{:?}", doubled_vec); // 这将打印:[2, 4, 6, 8]
}

在这个示例中,vec_map 接收 original_vec 的引用,创建了一个新的向量 doubled_vec,其中包含了原向量每个元素的两倍值,并打印出来。

Move Semantics

These exercises are adapted from pnkfelix's Rust Tutorial -- Thank you Felix!!!

Further information

For this section, the book links are especially important.

  • Ownership
  • Reference and borrowing

move_semantics1.rs

alt

move_semantics2.rs

alt
alt

// move_semantics5.rs

alt

Rust 中的可变引用有一条规则:在任意给定时间,你可以拥有任意数量的不可变引用,或者至多一个可变引用。这条规则确保了内存安全,防止了数据竞争。

在提供的代码中,存在一个问题:main 函数试图创建两个可变引用 yz,都指向同一个变量 x。这是不允许的,因为 Rust 的借用规则不允许在同一作用域内对同一变量有多个可变引用。这就是为什么代码无法编译的原因。

要修复这个问题,你需要确保在任何给定时间,只有一个可变引用存在。这里是修复后的代码:

fn main() {
    let mut x = 100;
    {
        let y = &mut x;
        *y += 100// 此时 x 的值变为 200
    } // 'y' 的作用域结束,可变引用被销毁
    {
        let z = &mut x; // 可以创建新的可变引用,因为 'y' 已经不存在了
        *z += 1000// 此时 x 的值变为 1200
    } // 'z' 的作用域结束,可变引用被销毁
    assert_eq!(x, 1200); // 断言 x 的值是 1200,这是正确的
}

在这个修复的版本中,我们通过创建内部作用域来确保在任何时候只有一个可变引用存在。首先,我们创建了 y 的作用域,对其进行了操作,然后这个作用域结束,y 不再有效。之后,我们创建了 z 的作用域,再次对 x 进行操作。这样就遵守了 Rust 的借用规则,使得代码可以编译并按预期运行。

alt
alt
alt

这段编译错误信息指出了 Rust 代码中的一个生命周期问题。问题出在 string_uppercase 函数的实现上,它试图将一个临时值赋给一个引用,这是不允许的。

这里是出错的代码行:

data = &data.to_uppercase();

在这行代码中,data.to_uppercase() 创建了一个 String 的新实例,这个实例是一个临时值,它的生命周期依赖于 data 的借用。然而,尝试将这个临时值的引用赋给 data 是不合法的,因为临时值会在语句结束时立即被销毁,而 data 需要一个比临时值更长的生命周期。

要修复这个问题,我们需要修改 string_uppercase 函数,让它接受一个可变引用,并且直接在该引用指向的数据上调用 make_uppercase() 方法,而不是尝试重新赋值。这里是修复后的代码:

fn string_uppercase(data: &mut String) {
    data.make_uppercase(); // 直接在 data 上调用 make_uppercase 方法

    println!("{}", data);
}

在这个修复版本中,我们移除了 mut data: &String 中的 mut,因为 data 已经是一个可变引用。然后我们直接在 data 上调用 make_uppercase(),这样就不会有临时值的问题。make_uppercase() 方法会修改 data 引用指向的 String 实例,而不需要创建新的 String

此外,main 函数中的调用也需要相应地更新,以传递一个可变引用:

fn main() {
    let mut data = "Rust is great!".to_string();

    string_uppercase(&mut data); // 传递一个可变引用
    println!("{}", data); // 打印修改后的字符串
}

现在,string_uppercase 函数接受 data 的可变引用,直接修改它,并且 main 函数中的 data 是可变的,可以被 string_uppercase 所修改。这样代码就可以编译并按预期工作了。

alt
alt
alt
/**
【昵称】小王同学
【坐标】山东
【自我介绍】
    1. 高级后端工程师,擅长c++并发编程。
    2. 专注分布式存储,分布式数据库。
    3. 时间的践行者,立志成为一名讲师。
【我的成绩】
    1.  为了走出农村,2次高考
         一次考研失败,
         遇挫之后不知道干什么,开启被动之旅。
    2. 为了找到合适工作,   
        深入研究c++书籍和leetcode 200题目
    3. 为了提高项目能力,参与开源项目建设。
    4. 为了把简单事情说清楚/要干啥
        按照《只管去做》,《福格行为模型>>方法。
        纸上得来终觉浅,绝知此事要躬行
        做一个践行者。
【我能提供】
    1.  后端程序员的简历优化+就业辅导+职业规划
    2.  全栈工程师(c++,rust,go,python )项目开发
    3. 一年践行12本书践行记录。
【希望一起解决什么,开启破圈之旅】
    1. 交接更多朋友,抱团取暖。
        寻找意义本身就更加有意义。
    2. 无法做整个系统,聚焦一个模块
         道可道也,非恒道也 
         名可名也,非恒名也。
         无名 万物之始也
         有名 万物之母也
         别想太多,只管去做,躬身入局
     
链接我: # + v(github):watchpoints   
        #众号:后端开发成长指南
**/

本文由 mdnice 多平台发布

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

建投数据入选“2024年中国最佳信创企业管理软件厂商”

近日&#xff0c;建投数据凭借国产化自主知识产权、完备的信创资质及信创软硬件环境全栈适配能力&#xff0c;入选第一新声联合天眼查发布的“2024年中国最佳信创厂商系列榜单”细分行业榜之“最佳信创企业管理软件厂商”。 本次最佳信创厂商系列榜单评选&#xff0c;包括综合榜…

从0-1实现一个前端脚手架

https://gitee.com/childe-jia/kfc-cli.git gitee完整地址 介绍 为什么需要脚手架&#xff1f; 脚手架本质就是一个工具&#xff0c;作用是能够让使用者专注于写代码&#xff0c;它可以让我们只用一个命令就生成一个已经配置好的项目&#xff0c;而不用我们再花时间去配置和安…

【python教程】数据分析——numpy、pandas、matplotlib

【python教程】数据分析——numpy、pandas、matplotlib 文章目录 什么是matplotlib安装matplotlib&#xff0c;画个折线 什么是matplotlib matplotlib:最流行的Python底层绘图库&#xff0c;主要做数据可视化图表,名字取材于MATLAB&#xff0c;模仿MATLAB构建 安装matplotlib&…

Idea-Idea配置gitIgnore忽略文件

背景 在项目提交到Git过程中&#xff0c;总有一些文件&#xff0c;例如.idea和.iml等这些我们不想提交的&#xff0c;直接添加进入gitIgnore文件中自动忽略掉。 Idea安装插件 1、在File->Setting->Plugins中搜索gitIgnore并安装插件 2、项目右键new->.ignore File-…

树状数组求三元上升子序列

分析一下&#xff0c;感觉没什么思路&#xff0c;再想一下&#xff0c;结果不就是每一位的数小于它的数乘以大于大于这位数的相乘之和吗&#xff0c;我们可以利用逆序对的思维求得 关键点在于求解逆序对的时候值相同的时候&#xff0c;位置大的优先级更高处理 #define _CRT_SEC…

Android OpenGL ES 离屏幕渲染1——EGL环境的创建,以及基础概念的理解

创建EGL上下文、配置EGL环境、创建EGL DISPLAY 什么是EGL&#xff1a; 由于OpenGL ES并不负责窗口管理以及上下文管理&#xff0c;该职责由各个平台自行完成&#xff1b;在Android平台下OpenGL ES的上下文环境是依赖EGL的API进行搭建的。 对于EGL这个框架&#xff0c;谷歌已经提…

抽象类和接口及内部类

1.抽象类 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c; 如果 一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类 2.接口 1.概念 接口就是公共…

树莓派5安装冬瓜HAOS教程

原文来自瀚思彼岸和hasshome 一、安装前准备 &#xff08;1&#xff09;软件 1、树莓派烧录软件Imager 2、冬瓜HAOS镜像 &#xff08;2&#xff09;硬件 1、树莓派5 2、TF卡&#xff08;SanDisk Extreme PRO 64GB U3 A2 V30 4k&#xff09; 3、读卡器 4、键盘和鼠标 5、显…

第一节 网络安全概述

一.网络空间安全 网络空间&#xff1a;一个由信息基础设施组成相互依赖的网络。 ---- 海陆空天&#xff08;大海、陆 地、天空、航天&#xff09; 通信保密阶段 ---- 计算机安全 ----- 信息系统安全 ----- 网络空间安全 计算机安全&#xff1a;开始秉持着“严于律己&#x…

网络防御保护——网络安全概述

一.网络安全概念 1.网络空间---一个由信息基础设施组成相互依赖的网络 。 网络空间&#xff0c;它跟以前我们所理解的网络不一样了&#xff0c;它不光是一个虚无缥缈的&#xff0c;虚拟的东西&#xff0c;它更多的是融入了我们这些真实的物理设备&#xff0c;也就意味着这个网…

synchronized和ReentrantLock

ReentrantLock ReentrantLock fairLock new ReentrantLock(true);// 这里是演示创建公平锁&#xff0c;一般情况不需要。 fairLock.lock(); try {// do something } finally {fairLock.unlock(); }

Google Earth Engine(GEE)——ui.Panel添加到地图上

结果 函数 ui.root.add(widget) 将一个widget添加到根面板上。 返回根面板。 参数。 widget&#xff08;ui.Widget&#xff09;。 要添加的widget。 返回&#xff1a; ui.Panel 代码 //label var label ui.Label({ value: "text label", style: {fontSi…

最近看English the American way一点小结

这个书还行吧&#xff0c;就是没很多时间去学。最后就是总结一些觉得还有用的短语和单词。 hang out drop by/in 来访 what are you up to? Thanks a bunch. tied up Stay tuned 敬请期待 hop on/into the bus/car. hail a cab off track 偏题了 in the same boat f…

代码随想录算法训练Day58|LeetCode417-太平洋大西洋水流问题、LeetCode827-最大人工岛

太平洋大西洋水流问题 力扣417-太平洋大西洋水流问题 有一个 m n 的矩形岛屿&#xff0c;与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界&#xff0c;而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个…

SQL 对一个经常有数据更新和删除操作的表,怎样优化以减少磁盘空间的占用?

文章目录 一、定期清理不再需要的数据二、使用合适的数据类型三、压缩数据四、删除重复数据五、分区表六、索引优化七、碎片整理八、归档历史数据九、监控和评估 在数据库管理中&#xff0c;当面对一个经常进行数据更新和删除操作的表时&#xff0c;磁盘空间的有效利用是一个重…

【国产开源可视化引擎Meta2d.js】钢笔

钢笔 钢笔是和其他众多绘图工具&#xff08;Photoshop、Sketch、Illustrator&#xff09;中一致的钢笔工具&#xff0c;能够很方便的在线绘制各种小图标 在线体验&#xff1a; 乐吾乐2D可视化 示例&#xff1a; // 开始绘画&#xff1a;curve。除了curve&#xff0c;还有poly…

【HTML入门】第三课 - 标题、段落、空格

这一小节&#xff0c;我们说一些比较零散的知识&#xff0c;HTML课程中呢&#xff0c;其实就是一些标签&#xff0c;正是这些标签组成了前端网页的各种元素&#xff0c;所以你也可以叫他们标签元素。 像前两节我们说的&#xff0c;html head body title meta style 。这些都是…

【Unity性能消耗】ScriptableObject复用数据节省内存占用

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…

【电商系统开发实用接口指南】包含国内国外多电商平台商品数据对接(附文档)

关于电商数据接口 开发电商系统的朋友对于电商平台API肯定不陌生&#xff0c;API接口即应用程序编程接口&#xff0c;电商平台开放部分API接口&#xff0c;供商家和服务商调用&#xff0c;以满足电商业务管理需求。随着电商市场需求的日益增长以及技术手段的不断成熟&#xf…

深度学习与CV入门

文章目录 前言历史 前言 历史 tensorflow可以安装Tensorboard第三方库用于展示效果 TensorFlow工作流程&#xff1a;p6-4:20 使用tf.data加载数据。使用tf.data实例化读取训练数据和测试数据模型的建立与调试:使用动态图模式Eager Execution和著名的神经网络高层API框架Ker…