当前位置: 首页 > news >正文

借用和引用

文章目录

  • 所有权
  • 引用和借用
    • 可变引用
    • 悬垂引用

所有权

Rust通过所有权来管理内存,最妙的是,这种检查只发生在编译期,因此对于程序运行期,不会有任何性能上的损失。

使用堆和栈的性能区别:

写入方面:入栈比在堆上分配内存要快。 因为入栈时操作系统无需分配新的空间,只需要将新数据放入栈顶即可。相比之下,在堆上分配内存则需要更多的工作,这是因为操作系统必须首先找到一块足够存放数据的内存空间,接着做一些记录为下一次分配做准备。

读取方面:出栈比读取堆上的数据快。 栈数据往往可以直接存储在 CPU 高速缓存中,而堆数据只能存储在内存中。访问堆上的数据比访问栈上的数据慢,因为必须先访问栈再通过栈上的指针来访问内存。

因此,处理器处理分配在栈上数据会比在堆上的数据更加高效。

Rust的所有权原则:

  1. Rust 中每一个值都被一个变量所拥有,该变量被称为值的所有者
  2. 一个值同时只能被一个变量所拥有,或者说一个值只能拥有一个所有者
  3. 当所有者(变量)离开作用域范围时,这个值将被丢弃(drop)

简单说就是每一个值(堆上的值)有且只有一个所有者(变量),当这个变量出了作用域,那么这个值也被丢弃(在堆上也会丢弃)。

看一段代码:

fn main(){let x: &str = "hello world";let y = x;println!("{},{}",x,y);
}

这段代码并不会报错,这是因为 x 在这里只是引用了字符串,没有所有权,所以 let y = x; 是对引用的拷贝,不会有所有权的转移(具体看下一节 “引用与借用” )

函数的传参和返回:

传参:

fn main() {let s = String::from("hello");  // s 进入作用域takes_ownership(s);             // s 的值移动到函数里 // s 所以到这里不再有效let x = 5;                      // x 进入作用域makes_copy(x);                  // x 应该移动函数里,// 但 i32 是 Copy 的,所以在后面可继续使用 x} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走,// 所以不会有特殊操作fn takes_ownership(some_string: String) { // some_string 进入作用域println!("{}", some_string);
} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放fn makes_copy(some_integer: i32) { // some_integer 进入作用域println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作

返回:

fn main() {let s1 = gives_ownership();         // gives_ownership 将返回值移给 s1let s2 = String::from("hello");     // s2 进入作用域let s3 = takes_and_gives_back(s2);  // s2 被移动到takes_and_gives_back 中,它也将返回值移给 s3
} 
// 这里, 
// s3 移出作用域并被丢弃。
// s2 也移出作用域,但已被移走,所以什么也不会发生。
// s1 移出作用域并被丢弃fn gives_ownership() -> String {  let some_string = String::from("hello"); // some_string 进入作用域.some_string                              // 返回 some_string 并移出给调用的函数
}// takes_and_gives_back 将传入字符串并返回该值
fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域a_string  // 返回 a_string 并移出给调用的函数
}

引用和借用

在 Rust 中,获取变量的引用叫做借用

引用:&x,解引用:*x;

用在函数参数和函数返回值:

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()
}

可变引用

引用默认是不能修改值的,想要修改值需要使用可变引用:

fn main() {let mut s = String::from("hello");change(&mut s);
}fn change(some_string: &mut String) {some_string.push_str(", world");
}

要注意的是,特定数据的可变引用在同一个作用域只能存在一个,并且,可变引用和不可变引用不能同时存在。

新旧编译器的引用作用域不同,旧编译器(1.31之前)的引用作用域结束于最近的花括号处,而新编译器的引用作用域改变为 最后一次使用的位置。

这种优化行为叫做 Non-Lexical LifeTimes(NLL).

悬垂引用

指引用指向某个值后,值被释放掉,指针仍然存在的情况。

在 Rust 中编译器可以确保引用永远也不会变成悬垂状态:当你获取数据的引用后,编译器可以确保数据不会在引用结束前被释放,要想释放数据,必须先停止其引用的使用。

释放引用:

fn dangle() -> &String { // dangle 返回一个字符串的引用let s = String::from("hello"); // s 是一个新字符串&s // 返回字符串 s 的引用
} // 这里 s 离开作用域并被丢弃。其内存被释放。// 危险!// 应该更改为
fn no_dangle() -> String {let s = String::from("hello");s
}

相关文章:

借用和引用

文章目录 所有权引用和借用可变引用悬垂引用 所有权 Rust通过所有权来管理内存,最妙的是,这种检查只发生在编译期,因此对于程序运行期,不会有任何性能上的损失。 使用堆和栈的性能区别: 写入方面:入栈比在…...

WPF上位机9——Lambda和Linq

Lambda Linq 操作集合 使用类sql形式查询 Linq To SQL...

从0到1搭建uniapp

一、什么是uniapp UniApp是一款基于Vue.js框架的全端开发工具,可以实现同时开发多个平台(包括H5、小程序、APP等)应用的能力。使用UniApp,开发者只需要编写一份代码就可以快速地发布到多个平台,极大地提高了开发效率和…...

安全杂记 - Linux文本三剑客之awk

目录 1.什么是AWK2.正则表达式3.语法4.内置变量示例printf命令5.复现awk经典实例(1).插入几个新字段(2).格式化空白(3).筛选IPv4地址(4).筛选给定时间范围内的日志 1.什么是AWK awk、grep、sed是linux操作文本的三大利器,合称文本三剑客。三者的功能都是处理文本&a…...

Android 开发者选项日志存储路径

android开发者选项中存在两个item是关于系统日志的。 1.日志记录器缓冲区大小 2.在设备上永久存储日志记录器数据 一个是用来设置缓冲区大小,一个是用来日志存储开关及过滤。 通过分析 system/core/logcat/logcatd.rc mkdir /data/misc/logd 0770 logd log 日志的…...

jupyter lab build失败,提示需要安装版本>=12.0.0的nodejs但其实已从官网安装18.17.0版本 的解决方法

出现的问题如题目所示,这个问题差点要把我搞死了。。。但还是在没有重装的情况下解决了😘。 问题来源 初衷是想安装lsp扩展,直接在jupyter lab网页界面的extensions中搜索lsp并点击install krassowski/jupyterlab-lsp,会提示需要…...

【set】个人练习-Leetcode-817. Linked List Components

题目链接&#xff1a;https://leetcode.cn/problems/linked-list-components/description/ 题目大意&#xff1a;给出一个vector<int> nums&#xff0c;其中有一些数字。再给出一个链表的头指针head&#xff0c;链表内的元素各不相同。如果链表中有某一段&#xff08;长…...

Linux IPIP隧道连通两个局域网

拓扑结构 现有两台主机&#xff0c;它们具有两个网口分别接入到不同网络中。 主机A&#xff1a; eth0&#xff1a;处于 10.0.1.2/24 网段eth1&#xff1a; 处于192.168.1.100/24 网段 主机B&#xff1a; eth0&#xff1a;处于10.0.2.3/24 网段eth1&#xff1a; 处于192.168.2…...

华为QinQ技术的基本qinq和灵活qinq 2种配置案例

基本qinq配置&#xff1a; 运营商pe设备在收到同一个公司的ce发来的的包&#xff0c;统一打上同样的vlan &#xff0c;如上图&#xff0c;同一个家公司两边统一打上vlan 2&#xff0c;等于在原内网vlan 10或20过来的包再统一打上vlan 2的标签&#xff0c;这样传输就不会和其它…...

python爬虫1:基础知识

python爬虫1&#xff1a;基础知识 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 目录结构 文章目录 python爬虫1&#xff1a;基础知识1. 基础认知1.1 什么是爬虫&…...

【FAQ】安防监控视频EasyCVR平台分发的FLV视频流在VLC中无法播放

众所周知&#xff0c;TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入&#xff0c;包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上&#xff0c;视频监控…...

python爬虫2:requests库-原理

python爬虫2&#xff1a;requests库-原理 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 目录结构 文章目录 python爬虫2&#xff1a;requests库-原理1. 概述2. re…...

纹理贴图和渲染

纹理贴图 纹理映射&#xff08;也就是纹理图或者叫做纹理贴图&#xff09;是一种在计算机图形学中常用的技术&#xff0c;它可以将二维的图像&#xff08;纹理&#xff09;映射到三维物体的表面上&#xff0c;以增强视觉效果。“atlas”通常是指纹理图集&#xff0c;也就是将多…...

BLIP2

BLIP2的任务是基于已有的固定参数的图像encoder和语言大模型&#xff08;LLM&#xff09;搭建一个具有图像理解能力的图文模型&#xff0c;输入是图像和文本&#xff0c;输出是文本。 BLIP2基于Q-Former结构&#xff0c;如下图所示。Q-Former包含图像transformer和文本transfo…...

陀螺玩具跨境电商亚马逊CPC认证

陀螺指的是绕一个支点高速转动的刚体。陀螺是中国民间最早的娱乐工具之一.形状上半部分为圆形&#xff0c;下方尖锐。从前多用木头制成&#xff0c;现代多为塑料或铁制。玩时可用绳子缠绕&#xff0c;用力抽绳&#xff0c;使直立旋转。或利用发条的弹力旋转。传统古陀螺大致是木…...

TS学习02-接口

接口 ts原则之一就是对值所具有的结构进行类型检查。 结构的左右就是为了这些类型命名和代码定义契约 interface LabelValue {label: string } function point(label: LabelValue) {} let obj {label:标题&#xff0c;age: 18} point(obj)类型检查器不会去检查属性的顺序&a…...

WuThreat身份安全云-TVD每日漏洞情报-2023-08-09

漏洞名称:致远OA文件上传漏洞 漏洞级别:高危 漏洞编号:NULL 相关涉及:1. A6、A8、A8N的V8.0SP2、V8.1、V8.1SP1 漏洞状态:POC 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-19494 漏洞名称:Microsoft Exchange Server 欺骗漏洞 漏洞级别:高危 漏洞编号:CV…...

6. C++类的静态成员

一、对象的生产期 生存期&#xff1a;对象从诞生到结束的这段时间生存期分为静态生存期和动态生存期 1.1 静态生存期 对象的生存期与程序的运行期相同&#xff0c;则称它具有静态生存期在文件作用域中声明的对象都是具有静态生存期的若在函数内部的局部作用域中声明具有静态…...

如何使Python Docker镜像安全、快速、小巧

一、说明 在微服务领域&#xff0c;拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素&#xff0c;包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构&…...

AWS——03篇(AWS之Amazon S3(云中可扩展存储)-01入门)

AWS——03篇&#xff08;AWS之Amazon S3&#xff08;云中可扩展存储&#xff09;-01入门&#xff09; 1. 前言2. 关于 Amazon S32.1 介绍2.1.1 简述2.1.2 详细介绍 2.2 Amazon S3 好处和功能2.3 3. 创建S3存储桶3.1 创建存储桶3.2 修改访问权限 4. 简单实用4.1 上传图片文件4.2…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...