rust变量绑定、拷贝、转移、引用
目录
一,clone、copy
1,基本类型
2,类型的clone特征
3,显式声明结构体的clone特征
4,类型的copy特征
5,显式声明结构体的clone特征
5,变量和字面量的特征
6,特征总结
二,变量绑定
1,clone拷贝场景
2,copy拷贝场景
3,所有权转移场景
4,转移的永久性
三,引用
1,对常量的引用
2,对变量的不可变引用
3,对变量的可变引用
5,函数调用
四,引用总结
1,引用的生命周期
2,对字面量的引用
3,对普通变量的引用
4,对引用变量的引用
5,对同一变量的引用
6,链式引用
一,clone、copy
1,基本类型
rust基本类型包括:
- 所有整数类型,比如
u32
- 布尔类型,
bool
,它的值是true
和false
- 所有浮点数类型,比如
f64
- 字符类型,
char
2,类型的clone特征
拥有clone特征的类型:
- 基本类型
- String
- 容器
- 显式声明clone特征的结构体
没有clone特征的类型:
- 没有显式声明clone特征的结构体(结构体默认)
递归决定是否有clone特征的类型:
- 元组,当且仅当其包含的类型都有clone特征的情况下,其自身有clone特征。
3,显式声明结构体的clone特征
前提条件:当且仅当结构体中的成员都具有clone特征的情况下,可以显式声明clone特征。
#[derive(Clone)]
struct S{}#[derive(Clone)]
struct P{a:i32,b:S,
}
4,类型的copy特征
拥有copy特征的类型:
- 基本类型
- 显式声明clone特征的结构体
没有copy特征的类型:
- String
- 容器
- 没有显式声明clone特征的结构体(结构体默认)
递归决定是否有copy特征的类型:
- 元组,当且仅当其包含的类型都有copy特征的情况下,其自身有copy特征。
5,显式声明结构体的clone特征
前提条件:结构体具有clone特征
#[derive(Clone,Copy)]
struct P{a:i32,
}fn main() {let x:P=P{a:5};let y=x;assert_eq!(x.a,5);
}
5,变量和字面量的特征
字面量会自动推导出类型,所以变量和字面量都有唯一确定的类型。
变量和字面量是否具有clone和copy特征,完全取决于其类型是否具有。
6,特征总结
所有类型可以分为3类:
没有clone和copy特征,有clone没有copy特征,有clone和copy特征。
二,变量绑定
1,clone拷贝场景
对于有clone特征的变量或字面量,可以调用clone函数进行拷贝而不转移所有权。
#[derive(Clone)]
struct P{a:i32,
}fn main() {let x:P=P{a:5};let y=x.clone();assert_eq!(x.a,5);
}
2,copy拷贝场景
如果let绑定语句的等号右边是一个有copy特征的变量或字面量,那么这是一个拷贝行为。
let x = 5;let xx = x;assert_eq!(5, x);assert_eq!(6, xx+1);
3,所有权转移场景
如果let绑定语句的等号右边是一个没有copy特征的变量或字面量,那么这是一个所有权转移的行为。
错误代码:
let x = vec![1,2,3];assert_eq!(x[0],1);let y=x;assert_eq!(x[0],1); // 错误
错误原因:y转移走了所有权,不能再使用x
4,转移的永久性
错误代码:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:5};{let y= x;}x.a=6;println!("end");
}
错误原因:y转移了x的所有权之后,x就再也不能用了,即使y的生命周期结束了也一样。
三,引用
1,对常量的引用
fn main() {let x:P=P{a:6};let y= & x;assert_eq!(x.a,6);assert_eq!(y.a,6);assert_eq!((*y).a,6);println!("end");
}
常量只有可读性,原变量x和引用变量y都持有读的能力。
这里y可以直接用,也可以先解引用再用。
2,对变量的不可变引用
正确代码:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:6};let y= &x;assert_eq!(x.a,6);assert_eq!(y.a,6);assert_eq!((*y).a,6);x.a=5;assert_eq!(x.a,5);println!("end");
}
变量x持有读写能力,不可变的引用y只有读能力。
错误代码:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:6};let y= &x;x.a=5;assert_eq!(y.a,5);println!("end");
}
错误原因:在y的读行为结束之前,x不能执行写行为,否则会造成冲突。
同一个变量可以引用多次,也可以对引用变量再进行引用:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:6};let y= &x;let z=&x;let z2=&z;let z3=&z2;let z4=&z3;assert_eq!(x.a,6);assert_eq!(y.a,6);assert_eq!(z.a,6);assert_eq!(z4.a,6);assert_eq!((*z4).a,6);assert_eq!((**z4).a,6);assert_eq!((***z4).a,6);assert_eq!((****z4).a,6);println!("end");
}
这里的z4可以直接读成员,也可以解引用若干次再使用。
3,对变量的可变引用
正确代码:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:6};let y= &mut x;assert_eq!(y.a,6);y.a=5;assert_eq!(x.a,5);println!("end");
}
错误代码:
struct P{a:i32,
}
fn main() {let mut x:P=P{a:6};let y= &mut x;assert_eq!(x.a,6);assert_eq!(y.a,6); println!("end");
}
错误原因:y的读写行为结束之前,x不能执行读行为,否则会造成冲突。
可变引用和不可变引用不能同时存在,否则会造成冲突。
5,函数调用
错误代码:
fn fun(x:Vec<i32>)->i32{x[0]+1
}fn main() {let x = vec![1,2,3];assert_eq!(fun(x),2);assert_eq!(x.len(), 3);println!("end");
}
错误原因:函数调用时转移走了所有权。
正确代码:
fn fun(x:&Vec<i32>)->i32{x[0]+1
}fn main() {let x = vec![1,2,3];assert_eq!(fun(&x),2);assert_eq!(x.len(), 3);println!("end");
}
实现方式:函数入参改成引用类型,传参时也要改成引用。
四,引用总结
1,引用的生命周期
(1)一个引用变量的声明周期只到它的最后一次读写为止
(2)如果声明了引用之后没有读写,那么生命周期直接结束,但是这和直接删除这一句不一样,因为声明引用这一行相当于一次读操作。
(3)如果一个引用变量y被z引用了,且z最后一次读写比y的最后一次读写更晚,那么y的生命周期延长到z的最后一次读写。
PS:如果声明了z是对y的引用之后没有读写,那么声明的这一句就是z的最后一次读操作,这也可能延长y的声明周期。
讨论引用规则时我们默认只讨论一个生命周期之内的引用。
2,对字面量的引用
对字面量的引用,无论是可变引用还有不可变引用,其实都不是引用,而是copy拷贝,讨论引用规则时我们默认不把对字面量的引用这个当做引用。
3,对普通变量的引用
对于普通变量,有mut的是可变变量,没有mut的是不可变变量(常量)。
可变变量可以加可变引用,也可以加不可变引用,不可变变量只能加不可变引用。
4,对引用变量的引用
无论是可变引用变量还是不可变引用变量,都和普通变量一样,可能是可变变量也可能是不可能变量。
对引用变量加引用的规则,和对普通变量一致。
5,对同一变量的引用
对不可变变量不能加可变引用,可以加多个不可变引用。
对可变变量可以加唯一的可变引用,也可以加多个不可变引用。
即,可变引用存在的情况下,只能有一个引用。
6,链式引用
以y是对x的引用,z是对y的引用为例,更长的链的情况应该规则类似。
y的声明周期参考上文“引用的生命周期”。
在所有情况下,z对x的读写能力都和y对x的读写能力相同,因为z一直持有对y的读能力。
(1)x是不可变变量
x和y 一直有读能力,没有写能力
(2)x是可变变量
在y的最后一次读操作或写操作之前,x没有读写能力,之后,x有读写能力
y的能力在声明周期内不变,有读能力,有没有写能力取决于是可变引用还是不可变引用。
五,ref
当我们要引用一个Option的内部成员,可以用ref
struct P{a:i32,
}
struct Node{x:Option<P>,
}
fn main() {let mut p = Node{x:Some(P{a:1})};if let Some(ref mut x)=p.x{x.a=2;}if let Some( x)=p.x{assert_eq!(x.a,2);}println!("end");
}
相关文章:

rust变量绑定、拷贝、转移、引用
目录 一,clone、copy 1,基本类型 2,类型的clone特征 3,显式声明结构体的clone特征 4,类型的copy特征 5,显式声明结构体的clone特征 5,变量和字面量的特征 6,特征总结 二&am…...
Java多种方式向图片添加自定义水印、图片转换及webp图片压缩
给个创建水印的示例: /*** 获取水印** param watermarkText 水印文字* return 水印bufferimage*/public static BufferedImage getWatermark(String watermarkText) {BufferedImage measureBufferdImage new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB…...
基于Pytorch框架的LSTM算法(二)——多维度单步预测
1.项目说明 **选用Close和Low两个特征,使用窗口time_steps窗口的2个特征,然后预测Close这一个特征数据未来一天的数据 当batch_firstTrue,则LSTM的inputs(batch_size,time_steps,input_size) batch_size len(data)-time_steps time_steps 滑动窗口&…...
cnn感受野计算方法
No. Layers Kernel Size Stride 1 Conv1 33 1 2 Pool1 22 2 3 Conv2 33 1 4 Pool2 22 2 5 Conv3 33 1 6 Conv4 33 1 7 Pool3 2*2 2 感受野初始值 l 0 1 l_0 1l 0 1,每层的感受野计算过程如下: l 0 1 l_0 1l 0 1 l 1 1 ( 3 − 1 ) 3 l_1 1…...

百分点科技受邀参加“第五届治理现代化论坛”
11月4日,由北京大学政府管理学院主办的“面向新时代的人才培养——第五届治理现代化论坛”举行,北京大学校党委常委、副校长、教务长王博,政府管理学院院长燕继荣参加开幕式并致辞,百分点科技董事长兼CEO苏萌受邀出席论坛…...

基于Springboot的智慧食堂设计与实现(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的智慧食堂设计与实现(有报告)。Javaee项目,springboot项目。 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 项…...

「Verilog学习笔记」多功能数据处理器
专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 注意题目要求输入信号为有符号数,另外输出信号可能是输入信号的和,所以需要拓展一位,防止溢出。 timescale 1ns/1ns module data_…...
OpenHarmony 4.0 Release 编译异常处理
一、环境配置 编译环境:Ubuntu 20.04 OpenHarmony 软件版本:4.0 Release 设备平台:rk3568 二、下拉代码 参考官网步骤: OpenHarmony 4.0 Release 源码获取 repo init -u https://gitee.com/openharmony/manifest -b OpenHarmo…...

软件测试|MySQL LIKE:深入了解模糊查询
简介 在数据库查询中,模糊查询是一种强大的技术,可以用来搜索与指定模式匹配的数据。MySQL数据库提供了一个灵活而强大的LIKE操作符,使得模糊查询变得简单和高效。本文将详细介绍MySQL中的LIKE操作符以及它的用法,并通过示例演示…...
linux防火墙设置
#查看firewall的状态 firewall-cmd --state (systemctl status firewalld.service) #安装 yum install firewalld #启动, systemctl start firewalld (systemctl start firewalld.service) #设置开机启动 systemctl enable firewalld #关闭 systemctl stop firewalld #取消…...
http 403
一、什么是HTTP ERROR 403 403 Forbidden 是HTTP协议中的一个状态码(Status Code)。可以简单的理解为没有权限访问此站,服务器受到请求但拒绝提供服务。 二、HTTP 403 状态码解释大全 403.1 -执行访问禁止。 403.2 -读访问禁止。 403.3 -写访问禁止。 403.4要…...

RAW图像处理软件Capture One 23 Enterprise mac中文版功能特点
Capture One 23 Enterprise mac是一款专业的图像处理软件,旨在为企业用户提供高效、快速和灵活的工作流程。 Capture One 23 Enterprise mac软件的特点和功能 强大的图像编辑工具:Capture One 23 Enterprise提供了一系列强大的图像编辑工具,…...

Linux 进程终止和等待
目录 一:进程常见的退出方法 1. main 函数返回值 2.调用 exit 3.调用 _exit 二:异常问题 三:进程等待 1.概念 2.进程等待的必要性 3.进程等待的方法 <1>:wait --- 系统调用 <2>:waitpid 进程…...

python用tkinter随机数猜数字大小
python用tkinter随机数猜数字大小 没事做,看到好多人用scratch做的猜大小的示例,也用python的tkinter搞一个猜大小的代码玩玩。 猜数字代码 from tkinter import * from random import randint# 定义确定按钮的点击事件 def hit(x,y):global s_Labprint(…...
程序员们保住自己饭碗
在现代社会中,程序员扮演着至关重要的角色。他们不仅仅是编写代码的人,更是保障数字世界安全稳定的守护者。随着科技的迅猛发展,程序员保住自己饭碗的护城河变得愈发重要。本文将探讨程序员如何通过不断学习、技术创新和软实力的发展…...

顶板事故防治vr实景交互体验提高操作人员安全防护技能水平
建筑业在我国各行业中属危险性较大且事故多发的行业,在建筑业“八大伤害”(高处坠落、坍塌、物体打击、触电、起重伤害、机械伤害、火灾爆炸及其他伤害)事故中,高处坠落事故的发生率最高、危险性极大。工地现场培训vr坠落体验利用虚拟现实技术还原各种情…...

为什么推荐从Linux开始了解IT技术
IT是什么,是干什么的呢? 说起物联网,云计算,大数据,或许大家听过。但是,你知道,像云计算的底层基座是什么呢?就是我们现在说的Linux操作系统。而云计算就是跑在Linux操作系统上的一个…...

【Mysql】增删改查(基础版)
我使用的工具是Data Grip (SQLyog Naivact 都行) 使用Data Grip创建student表,具体步骤如下(熟悉Data Grip或者使用SQLyog,Naivact可以跳过) https://blog.csdn.net/m0_67930426/article/details/13429…...

文件夹找不到了怎么恢复?4个正确恢复方法分享!
“我在电脑上保存了很多的文件和文件夹,今天在查找文件时,发现我有一整个文件夹都消失了,不知道怎么才能找到呢。有朋友可以帮帮忙吗?” 电脑中文件夹突然找不到了可能会引发焦虑,尤其是如果这些文件夹包含重要的数据。…...

迅为RK3568开发板GPS模块测试实验步骤
1 首先按照上个实验-串口实验,在设备树中打开串口 9 的节点。 2 然后将 GPS 模块连接好之后,用 U 盘将 GPS 测试程序 gps_test 拷贝到开发板的/mnt 目录下。本小节的测试程序存放路径为“iTOP-3568 开发板\02_ 【iTOP-RK3568 开发板】开发资…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...