study Rust-4【所有权】这个太重要了!
由于Rust内存垃圾自动回收,那就得搞清楚这个所有权玩意。这个太重要了。因为关系到贯穿于你以后的程序编写。
几个概念:
一、移动
1、咱们一般语言,自己申请内存,自己管理和释放。就是new和free。
咱们搞不好就内存泄漏。
2、看Rust
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1); // 错误!s1 已经失效
Rust内存管理看下图【 这就是Rust的移动管理】:
传统的内存管理看图:
二、克隆
Rust会尽可能地降低程序的运行成本,所以默认情况下,长度较大的数据存放在堆中,且采用移动的方式进行数据交互。但如果需要将数据单纯的复制一份以供他用,可以使用数据的第二种交互方式——克隆。
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
s1 = hello, s2 = hello
运行结果。
这里是真的将堆中的 "hello" 复制了一份,所以 s1 和 s2 都分别绑定了一个值,释放的时候也会被当作两个资源。
当然,克隆仅在需要复制的情况下使用,毕竟复制数据会花费更多的时间。
三、涉及函数的所有权机制
//请仔细看注释,已经把过程说明很清楚了
fn main() {
let s = String::from("hello");
// s 被声明有效 takes_ownership(s);
// s 的值被当作参数传入函数
// 所以可以当作 s 已经被移动,从这里开始已经无效 let x = 5;
// x 被声明有效 makes_copy(x);
// x 的值被当作参数传入函数
// 但 x 是基本类型,依然有效
// 在这里依然可以使用 x 却不能使用 s } // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放 fn takes_ownership(some_string: String) {
// 一个 String 参数 some_string 传入,有效
println!("{}", some_string);
} // 函数结束, 参数 some_string 在这里释放 fn makes_copy(some_integer: i32) {
// 一个 i32 参数 some_integer 传入,有效
println!("{}", some_integer);
} // 函数结束, 参数 some_integer 是基本类型, 无需释放
//函数返回值的所有权机制
fn main() {
let s1 = gives_ownership();
// gives_ownership 移动它的返回值到 s1 let s2 = String::from("hello");
// s2 被声明有效 let s3 = takes_and_gives_back(s2);
// s2 被当作参数移动, s3 获得返回值所有权
} // s3 无效被释放, s2 被移动, s1 无效被释放. fn gives_ownership() -> String {
let some_string = String::from("hello");
// some_string 被声明有效 return some_string;
// some_string 被当作返回值移动出函数
} fn takes_and_gives_back(a_string: String) -> String {
// a_string 被声明有效 a_string // a_string 被当作返回值移出函数
}
四、引用与租借【这段理解简单,但是使用复杂,比较绕】
引用(Reference)是 C++ 开发者较为熟悉的概念。
如果你熟悉指针的概念,你可以把它看作一种指针。
实质上"引用"是变量的间接访问方式。
fn main() {
let s1 = String::from("hello");
let s2 = &s1;
println!("s1 is {}, s2 is {}", s1, s2);
}
//运行结果:s1 is hello, s2 is hello
=================================
fn main() {
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()
}
结果:The length of 'hello' is 5.
引用不会获得值的所有权。
引用只能租借(Borrow)值的所有权。
引用本身也是一个类型并具有一个值,这个值记录的是别的值所在的位置,但引用不具有所指值的所有权:
容易绕的地方:
fn main() {
let s1 = String::from("hello");
let s2 = &s1;//s2 租借的
let s3 = s1;//s1所有权转移到s3了,所以s2将无法继续租借使用s1的所有权,s2也就无效了
println!("{}", s2);
}
====================
//租来的只有使用权,不可编辑修改。看下面
fn main() {
let s1 = String::from("run");
let s2 = &s1;
println!("{}", s2);
s2.push_str("oob"); // 错误,禁止修改租借的值
println!("{}", s2);
}
=======================
你非要对租来的进行行使所有权,这样做:
fn main() {
let mut s1 = String::from("run");
// s1 是可变的
let s2 = &mut s1;
// s2 是可变的引用
s2.push_str("oob");
println!("{}", s2);
}
=====================
//可变引用与不可变引用相比除了权限不同以外,可变引用不允许多重引用,但不可变引用可以.下面是错误的
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;//多重引用,错误的
println!("{}, {}", r1, r2);
垂悬引用(Dangling References)【这个好理解】
这是一个换了个名字的概念,如果放在有指针概念的编程语言里它就指的是那种没有实际指向一个真正能访问的数据的指针(注意,不一定是空指针,还有可能是已经释放的资源)。它们就像失去悬挂物体的绳子,所以叫"垂悬引用"。
"垂悬引用"在 Rust 语言里不允许出现,如果有,编译器会发现它。
study Rust-4【所有权】这个太重要了!的更多相关文章
- Rust所有权语义模型
编程语言的内存管理,大概可以分为自动和手动两种. 自动管理就是用 GC(垃圾回收)来自动管理内存,像 Java.Ruby.Golang.Elixir 等语言都依赖于 GC.而 C/C++ 却是依赖于手 ...
- Rust所有权及引用
Rust 所有权和借用 Rust之所以可以成为万众瞩目的语言, 就是因为其内存安全性. 在以往内存安全几乎全都是通过GC的方式实现, 但是GC会引来性能.CPU以及Stop The World等问题, ...
- Rust之路(4)——所有权
[未经书面同意,严禁转载] -- 2020-10-14 -- 所有权是Rust的重中之重(这口气咋像高中数学老师 WTF......). 所有权是指的对内存实际存储的数据的访问权(包括读取和修改),在 ...
- 【Rust学习】内存安全探秘:变量的所有权、引用与借用
作者:京东零售 周凯 一.前言 Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月,是一种高效.可靠的通用高级语言.其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有 ...
- Rust语言:安全地并发
http://www.csdn.net/article/2014-02-26/2818556-Rust http://www.zhihu.com/question/20032903 Rust是近两年M ...
- Rust 入门 (四)
所有权是 rust 语言独有的特性,它保证了在没有垃圾回收机制下的内存安全,所以理解 rust 的所有权是很有必要的.接下来,我们来讨论所有权和它的几个特性:借用.切片和内存结构. 什么是所有权 Ru ...
- Rust之路(3)——数据类型 下篇
[未经书面同意,严禁转载] -- 2020-10-14 -- 架构是道,数据是术.道可道,非常道:术不名,不成术!道无常形,术却可循规. 学习与分析数据类型,最基本的方法就是搞清楚其存储原理,变量和对 ...
- 最强肉坦:RUST多线程
Rust最近非常火,作为coder要早学早享受.本篇作为该博客第一篇学习Rust语言的文章,将通过一个在其他语言都比较常见的例子作为线索,引出Rust的一些重要理念或者说特性.这些特性都是令人心驰神往 ...
- 5分钟APIG实战: 使用Rust语言快速构建API能力开放
序言:Rust语言简介 参与过C/C++大型项目的同学可能都经历过因为Null Pointer.Memory Leak等问题“被” 加班了不知道多少个晚上.别沮丧,你不是一个人,Mozilla Fir ...
- Rust到底值不值得学--Rust对比、特色和理念
前言 其实我一直弄不明白一点,那就是计算机技术的发展,是让这个世界变得简单了,还是变得更复杂了. 当然这只是一个玩笑,可别把这个问题当真. 然而对于IT从业者来说,这可不是一个玩笑.几乎每一次的技术发 ...
随机推荐
- C# WinForm 托盘程序
实现步骤 创建 NotifyIcon 控件并设置属性: 编写 NotifyIcon 响应控制事件: 在主窗体的Load事件中将 NotifyIcon 添加到系统托盘: 程序退出时,移除系统托盘的 No ...
- smart_web 管理端基本说明
smart_web 操作手册 1. smart_web 是什么? smart_web 是 smart_rtmpd 的付费版本,拥有比免费版本更多的功能支持,基于 web 的管理方式,让您随时随地在大部 ...
- Go语言【Gin框架】:JSON、AsciiJSON、PureJSON和SecureJSON的区别
在Go语言中,JSON.AsciiJSON.PureJSON 和 SecureJSON 是Gin框架用于发送JSON响应的方法. 1. c.JSON 功能:将提供的数据序列化为标准的JSON格式,并将 ...
- Windows下使用Bat拷贝远程共享目录下文件
哈喽 我又来了 客户昨天提出了一个要求,这次的update里要用bat脚本去拷贝远程共享目录下的文件到各自的本地C盘目录下,于是乎,从昨天下午开始研究 到了今天中午,写写删删,乱改一气,总算弄出来 ...
- 探秘Transformer系列之(1):注意力机制
探秘Transformer系列之(1):注意力机制 0x00 概述 因为各种事情,好久没有写博客了,之前写得一些草稿也没有时间整理(都没有时间登录博客和微信,导致最近才发现好多未读消息和私信,在这里和 ...
- 管理虚拟机(virsh)
[root@kvm1 qemu]# virsh --help 开启和关闭 [root@kvm1 qemu]# virsh virsh # help list virsh # list virsh # ...
- 用python做时间序列预测六:相关函数图、偏相关函数图、滞后图
经典的时间序列预测方法都是假设如果一个时间序列有显著的自相关性,那么历史值对预测当前值会很有帮助,但是究竟取多少阶的历史值,就需要通过分析相关函数图和偏相关函数图来得到.本文介绍如何什么是相关函数图和 ...
- DeepSeek本地部署
一.ollama ollama是一个管理和运行所有大模型.开源大模型的平台.在官网的Models中可以看到deepseek-r1的AI模型 1.在官网中下载对应系统的ollama,下载时需要开墙,或者 ...
- el-radio-group初始化默认值后点击无法切换问题/vue中设置表单对象属性页面不同步问题
<el-radio-group v-model="ruleForm.type"> <el-radio :label="1">方案一< ...
- Ubuntu 部署饥荒联机版服务器 Linux DST_Dedicate_Server
0. 文件夹 - ~ |- ~/steamcmd # 装的是steamcmd_linux.tar.gz以及其解压出来的东西 |- ~/DST # 装的是DST服务器可执行文件.世界存档.世界模板 |- ...