rust所有权理解(备忘)

2024-04-12 12:08
文章标签 rust 理解 备忘 所有权

本文主要是介绍rust所有权理解(备忘),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近闲的没事,就准备学习一下rust。 rust是Mozilla开发的一门编程语言。
rust是为了多核系统而设计的一门编程语言,它因其特殊的机制有线程安全性,编译期查出内存错误的优点,可能语法有着那么点另类,但我想这不是问题。至于它和另外一门编程语言GO的优缺点,请自行了解,因为我也是小白,并不敢发表什么高见。
本文只是用自己的语言再次理解了一些rust的所有权机制,官方的文档应该比我更加详尽。有兴趣的可以去看看,
地址: https://www.rust-lang.org/zh-CN/

正如上文所说,rust有编译期查错的能力以及线程安全的能力,这就是rust的特有机制,所有权机制。

首先我们先看一下所有权机制的规则(摘自官方文档):
1.Rust 中的每一个值都有一个叫做它的所有者(owner)的变量。2.同时一次只能有一个所有者3.当所有者变量离开作用域,这个值将被丢弃。

         我们接下来会用代码的形式来进行讲解,不懂的可以去官方文档看看语法。

首先我们看一段代码
{let x = String::from("test");println!("in scope hello this is {}", x);}println!("out scope hello this is {}", x);

         当然,这段代码是无法执行的,因为根本无法通过编译,报错如下
error[E0425]: cannot find value `x` in this scope--> src/main.rs:13:40|
13 | println!("out scope hello this is {}", x);|                                        ^ not found in this scope
  因为x在为这个String的值的所有者,在所有者离开作用域后值直接被释放了,这一点和其它编程语言是很相似的。


接下来我们看这一段代码
let x = String::from("123");let y = x;println!("x = {}, y = {}", x, y);

你们可能此时也已经在猜测运行结果了,很遗憾,这段代码也是无法运行的

报错为:
error[E0382]: use of moved value: `x`--> src/main.rs:11:32|
10 |     let y = x;|         - value moved here
11 |     println!("x = {}, y = {}", x, y);|                                ^ value used here after move|= note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait

 报错上显示x的值被移动了,你们可能在想,这是什么鬼。我们接下来就来扯一下数据的内存吧

实际上x是所有者,指向了堆上的一块内存,因为在rust中,非基本数据类型都是存储在堆上的,其它语言基本也是这样的。而let x = String::from("123");这个语言实际上是将x指向了那块内存。而let y = x则是将y指向了与x指向内存相同的那块内存。在其它语言中也是这样的,因为复制堆上的数据对运行效率影响很大。如果你们有其它语言的基础,那么这个过程其实就是浅拷贝,同时你们也应该了解这样会导致什么错误的出现,即任何该值的所有者均可对这块内存进行修改甚至删除,而rust解决了这个问题,rust使第一个变量,即x无效化了,这样就不会出现上述的问题了,这个就是数据的移动,是不是很形象。

那么我们再看另外一段代码:

let x = 1;let y = x;println!("x = {}, y = {}", x, y);
是不是觉得这段代码也不能执行,这就错了,这段代码可以正常执行,并且运行结果如你所想。因为在rust中,基本数据类型是存储这栈上的,而对栈的拷贝操作对运行效率的影响是微乎其微的,所以对栈上数据的引用都是默认是拷贝的。所以对于上一段代码其实也是可以对x进行深拷贝从而让它成功运行的。但是这样正如前面所说的,会影响运行效率。所以rust为了兼顾运行效率和安全,它使用了无效化这个方法。当然这个方法也会导致相应的问题,例如:
fn hello(str: String){println!("{}", str);}fn test(){let x = String::from("123");hello(x);println!("x = {}", x);}


这个会编译失败,报错为
error[E0382]: use of moved value: `x`--> src/main.rs:15:24|
14 |     hello(x);|           - value moved here
15 |     println!("x = {}", x);|                        ^ value used here after move|= note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait

因为x的值已经被转移到了hello函数的str参数中了,所以x无效化了,故而会导致这个错误。这个问题我们当然可以通过让hello函数返回x的值来解决,但是这个解决办法略显蛋疼,而且rust已经为我们解决了更好的方案了,具体的我们下篇文章再讲,如果我记得写的话(笑:-D),当然你们也可以去看rust的文档。习惯了以rust的所有权系统来编程,你在编写其它编程语言的时候也能写成更加安全的代码
String in memory

这篇关于rust所有权理解(备忘)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/897092

相关文章

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的