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

Rust 中的String与所有权机制

文章目录

  • 一、string
  • 二、所有权
    • 2.1 所有权与作用域
    • 2.2 对所有权的操作
      • 2.2.1 转移
      • 2.2.3 拷贝
      • 2.2.3 传递
    • 2.3 引用
      • 2.3.1 借用
      • 2.3.2 可变引用

一、string

之前学习过 Rust 只有几种基础的数据类型,但是没有常用的字符串也就是String,今天来学习一下 String;
Rust 中 String 是标准库的一部分,也就是 std::String , 但是这个 String 与其他语言中的 String 稍有不同,比如:
在这里插入图片描述

可以看到,当我想要以一种为指定字符串类型的方式定义了一字符串变量时,编译器自动显示出的类型是 &srr 而非 String, 而我指定了 String 类型后仍然有错;而从编译器给出的提示不难看出,“hello” 这样定义得到的是一个 “&str” 类型的值而非是个字符串,那么我们先假定这是一种未知的类型,后续再处理它,先去想办法定义出我们的字符串,打开官方文档: https://doc.rust-lang.org/std/string/struct.String.html

可以看到官方文档第一个示例告诉我们要像这样创建字符串:
在这里插入图片描述

但是官方没说为什么要这样定义,幸好 Rust 的源码是可以点进去的, 从 String::from 向里一步步执行:
在这里插入图片描述

from 执行的操作只有一个就是调用 to_owned 函数,但是需要注意,这里传进来的参数类型仍然是"&str"; 然后 to_owned 下一步是调用 as_bytes().to_owned() ,最后这个 to_owned() 则是调用了 to_vec ;
那么至此也就明白了,对于这一行代码:

    let hello = String::from("Hello, ");

我们传入的 “Hello,” 这会被编译器认为是一个字符数组,也就是一个字符串常量,即无法对其造成改变的一个对象;但是我们需要的是一个可变的字符串而非一组固定的字符,因此编译器将这个字符数组扩展为了一个 vector , 也就变成了一个可变的字符数组,也就是我最终想要的字符串;

其实这和C++差不多,只不过C++string底层应该直接是个指针而不是个vector

这样一来 “&str” 也就理解了,就是一个常量字符数组,所以是不可变的。在官方文档搜一下,果然也有,并且还有个好听的名字,字符串切片(string slice),具体参考: https://doc.rust-lang.org/std/primitive.str.html

官方文档中还介绍了两种类型的互转方法:
在这里插入图片描述

剩下的使用就是这两种类型自带的一些接口了,具体请参阅官方文档,这里不再细述;

二、所有权

2.1 所有权与作用域

很多小伙伴开始学习 Rust 是因为听说这是一种比C++更安全的语言,所以来了解一下,那么它安全在哪里?就安全在所有权机制,不再需要开发者像C++一样的去人工管理内存。

首先,所有程序都必须管理其运行时使用计算机内存的方式。一些语言中具有垃圾回收机制,在程序运行时有规律地寻找不再使用的内存,比如Java;另一些语言中,程序员必须亲自分配和释放内存,比如C/C++。Rust 则选择了第三种方式:通过所有权系统管理内存,编译器在编译时会根据一系列的规则进行检查。如果违反了任何这些规则,程序都不能编译。在运行时,所有权系统的任何功能都不会减慢程序。所有权有以下规则:

* Rust 中的每一个值都有一个 所有者(owner)。
* 值在任一时刻有且只有一个所有者。
* 当所有者(变量)离开作用域,这个值将被丢弃。

举个例子,有以下一段代码:

fn main() {let s1 = "hello";{                let s = "hello s"; }  let s2 = "hello";
}

在上面的代码中, s 被一个括号圈住了,那么在这个括号里"hello s" 的所有者就是 s,而 s 的生命周期也只在括号范围内,也就是 s1 出现时 s 未出现, s2 出现时 s 已经死去。

有过C++ 经验的小伙伴看到这肯定很熟悉,这不就是 RAII 吗,或者说 Rust 中的每个变量都是个智能指针。

2.2 对所有权的操作

2.2.1 转移

刚刚说到这种所有权机制与C++的 RAII 很像,变量也和智能指针很像,那么是不是就和智能指针一样呢,测试一下:
在这里插入图片描述

图上可以看到,先定义了 s1 ,然后定义 s2 ,然后将 s1 传递给 s2 ,此时再使用 s1 会报错,提醒你s1 的值已经被转移出去了, 这时 s1 就已经被清空了。因为 Rust 变量离开作用域时会回收,所以如果这里不清空,在程序结束时s1 s2都会被回收,那么一块内存就会回收了两次,因此 Rust 的机制中 = 操作是转移而非拷贝。

看到这里,还是觉得是智能指针,只不过是unique_ptr,QAQ

2.2.3 拷贝

= 是转移而不是拷贝,那么想要使用拷贝该怎么写呢?比如字符串这样:
在这里插入图片描述

调用 clone 函数就行了。

然后有一个很有意思的事情,比如:
在这里插入图片描述

i32 类型变量不需要使用 clone 之类的函数,= 居然就是拷贝而不是转移;
官方给出的解释是 “像整型这样的在编译时已知大小的类型被整个存储在栈上,所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 y 后使 x 无效。” 恕我直言,这不就是Rust中所有用到堆的变量就用的是智能指针吗。。。。。当然也可能是我理解不够深,反正我目前为止的感受就是这样。。。。

2.2.3 传递

之前提到过 “值在任一时刻有且只有一个所有者” ,那么如果将值传递给函数会怎么样呢:
在这里插入图片描述

很明显,作为参数传递给函数之后就失去了所有权;
但这样会带来一个问题,这个值如果不只一个函数再用后续怎么办?用函数返回值返回!
但是如果参数不只有一个呢?为每个函数的返回值都定一个结构体?
这样太麻烦了,万幸的是 Rust 提供了 引用。

2.3 引用

2.3.1 借用

官方说明中“引用(reference)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。 与指针不同,引用确保指向某个特定类型的有效值。”
很好理解,改一下刚才的代码:
在这里插入图片描述

可以用了,修改就是函数声明参数时加了一个&,传参时也加了一个&;

变量 str 有效的作用域与函数参数的作用域一样,不过当 str 停止使用时并不丢弃引用指向的数据,因为 str 并没有所有权。当函数使用引用而不是实际值作为参数,无需返回值来交还所有权,因为就不曾拥有所有权。

Rust 将创建一个引用的行为称为 借用(borrowing)。正如现实生活中,如果一个人拥有某样东西,你可以从他那里借来。当你使用完毕,必须还回去,并不拥有它,因此借用的值无法修改。
在这里插入图片描述

2.3.2 可变引用

正如不可变变量与可变变量一样,引用也可以变为可变引用,加个 mut 关键试试:
在这里插入图片描述

当然,像这段代码所写的,想要成为可变引用的前提是自身就是可变的。
另外,由于 Rust 的三条基础规则之“值在任一时刻有且只有一个所有者”,那么对于一个可变变量在同一个时刻也就不可以有多个引用;换个角度理解比如用一个 s1 作为 s 的可变引用后,那么 s 将不再可用,也自然不能再对一个无法使用的变量创建引用,如果这样使用编译器就会报错:
在这里插入图片描述

相关文章:

Rust 中的String与所有权机制

文章目录 一、string二、所有权2.1 所有权与作用域2.2 对所有权的操作2.2.1 转移2.2.3 拷贝2.2.3 传递 2.3 引用2.3.1 借用2.3.2 可变引用 一、string 之前学习过 Rust 只有几种基础的数据类型,但是没有常用的字符串也就是String,今天来学习一下 String…...

多线程环境下如何安全的使用线性表, 队列, 哈希表

小王学习录 今日鸡汤安全使用ArrayList安全使用队列安全使用HashMap 今日鸡汤 安全使用ArrayList 使用synchronized锁或者reentrantLock锁使用CopyOnWriteArrayList(COW写时拷贝)类来代替ArrayList类. 多个线程对CopyOnWriteArrayList里面的ArrayList进行读操作, 不会发生线程…...

机器人SLAM与自主导航

机器人技术的迅猛发展,促使机器人逐渐走进了人们的生活,服务型室内移动机器人更是获得了广泛的关注。但室内机器人的普及还存在许多亟待解决的问题,定位与导航就是其中的关键问题之一。在这类问题的研究中,需要把握三个重点&#…...

Zookeeper集群 + Kafka集群的详细介绍与部署

文章目录 1. Zookeeper 概述1.1 简介1.2 Zookeeper的工作机制1.3 Zookeeper 主要特点1.4 Zookeeper 数据结构1.5 Zookeeper的相关应用场景1.5.1 统一命名服务1.5.2 统一配置管理1.5.3 统一集群管理1.5.4 服务器动态上下线1.5.5 软负载均衡 1.6 Zookeeper 选举机制1.6.1 第一次启…...

STP、堆叠与VRRP如何使用

✍ STP生成树用在哪里? ✍ STP和堆叠有什么区别? ✍ VRRP双网关热备份如何部署? --- 通过交换机组成网络是局域网,连接终端设备的交换机就是接入层交换机。 --- 如上组网结构单一,不需要网工。 容易发生单点故障&…...

Go 函数的健壮性、panic异常处理、defer 机制

Go 函数的健壮性、panic异常处理、defer 机制 文章目录 Go 函数的健壮性、panic异常处理、defer 机制一、函数健壮性的“三不要”原则1.1 原则一:不要相信任何外部输入的参数1.2 原则二:不要忽略任何一个错误1.3 原则三:不要假定异常不会发生…...

Maven的详细介绍(maven的全据配置以及idea中maven的配置)

maven的理解 Maven 是一个强大的项目管理和构建自动化工具,它通过抽象的项目对象模型(POM:Project Object Model)和构建生命周期模型(Project Lifecycle)来对项目及其构建过程进行管理(Dependency Management System),Maven 最大化的消除了构…...

Qt中Json的操作

在 Json的两种格式中介绍了Json的格式以及应用场景。由于这种数据格式与语言无关,下面介绍一下Json在Qt中的使用。 从Qt 5.0开始提供了对Json的支持,我们可以直接使用Qt提供的Json类进行数据的组织和解析。相关的类常用的主要有四个,具体如下: Json类介绍 QJsonDocument |…...

10. 机器学习-评测指标

Hi,你好。我是茶桁。 之前的课程中,我们学习了两个最重要的回归方法,一个线性回归,一个逻辑回归。也讲解了为什么学习机器学习要从逻辑回归和线性回归讲起。因为我们在解决问题的时候,有限选择简单的假设,越复杂的模型…...

SAP-QM-动态检验规则

Dynamic Modification Rule (动态修改规则) 1、决定样本大小的方式有3种: 手动输入比例大小采样过程 物料主数据质量视图 2、采样过程的创建方式有2种 跟批量大小有关系:百分比/AQL跟批量大小没有关系:固定值 而当…...

CCC数字钥匙设计【NFC】--NFC卡相关基础知识

CCC3.0的NFC技术中,除车端,手机端需包含NFC功能外,另外一般还会配置一个NFC卡,用于备份使用。本文主要介绍NFC卡相关的基础知识。 1、NFC卡 & 智能卡 NFC卡是一种智能卡,其与信用卡大小相同,可通过嵌入…...

SpringMVC(第一个项目HelloWorld))

文章目录 1.在maven引入依赖2.配置web.xml3.创建请求控制器4.创建springMVC的配置文件5.测试HelloWorld总结 1.在maven引入依赖 <dependencies><!-- SpringMVC --><dependency><groupId>org.springframework</groupId><artifactId>spring…...

GEO生信数据挖掘(九)肺结核数据-差异分析-WGCNA分析(900行代码整理注释更新版本)

第六节&#xff0c;我们使用结核病基因数据&#xff0c;做了一个数据预处理的实操案例。例子中结核类型&#xff0c;包括结核&#xff0c;潜隐进展&#xff0c;对照和潜隐&#xff0c;四个类别。第七节延续上个数据&#xff0c;进行了差异分析。 第八节对差异基因进行富集分析。…...

二进制明文字符串加密:实现原理

二进制明文字符串加密:实现原理 背景 这里就不多做解释了&#xff0c;明文字符串暴露就是最好的逆向分析指引。无论是恶意攻击样本还是有一定安全需求的组件&#xff0c;直接暴露程序中的明文字符串会大幅降低外部的分析成本。所以需要在编译出的二进制中隐藏字符串。不过需要…...

免费SSL证书:JoySSL让您的网站更安全

在今天的数字化时代&#xff0c;保护网站和用户信息的安全至关重要。SSL&#xff08;Secure Sockets Layer&#xff09;证书通过加密网站与用户之间的通信&#xff0c;确保数据传输的安全性。让您拥有一个SSL加密的网站是至关重要的&#xff0c;但您可能会担心高昂的费用。不过…...

JavaPTA练习题 7-3 打印99乘法表

打印99乘法表 输入样例: 不需要输入 输出样例: 在这里给出相应的输出。要求&#xff1a;99乘法表中&#xff0c;每个表达式的乘法结果长度为3。 1x11 2x12 2x24 3x13 3x26 3x39 4x14 4x28 4x312 4x416 5x15 5x210 5x315 5x420 5x525 6x16 6x212 6x318 6x424…...

k8s-20 hpa控制器

hpa可通过metrics-server所提供pod的cpu 或者内存的负载情况&#xff0c;从而动态拉伸控制器的副本数&#xff0c;从而达到后端的自动弹缩 官网&#xff1a;https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/ 上传镜像 压测 po…...

操作系统【OS】操作系统的引导

激活CPU。 激活的CPU读取ROM中的boot程序&#xff0c;将指令寄存器置为BIOS(基本输入输出系统)的第一条指令&#xff0c; 即开始执行BIOS的指令。硬件自检。 启动BIOS程序后&#xff0c;先进行硬件自检&#xff0c;检查硬件是否出现故障。如有故障&#xff0c;主板会发出不同含…...

PHP的四层架构

PHP的4层架构是一种软件设计模式&#xff0c;用于将一个PHP应用程序划分为不同的层次&#xff0c;以实现解耦、可扩展和易于维护的代码结构。这个架构通常由以下四个层次组成&#xff1a; 1、 表现层&#xff08;Presentation Layer&#xff09;&#xff1a; 表现层是与用户直…...

Kafka存取原理与实现分析,打破面试难关

系列文章目录 上手第一关&#xff0c;手把手教你安装kafka与可视化工具kafka-eagle Kafka是什么&#xff0c;以及如何使用SpringBoot对接Kafka 架构必备能力——kafka的选型对比及应用场景 Kafka存取原理与实现分析&#xff0c;打破面试难关 系列文章目录一、主题与分区1. 模型…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

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

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