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

Rust基础语法1

    所有权转移,Rust中没有垃圾收集器,使用所有权规则确保内存安全,所有权规则如下:

    1、每个值在Rust中都有一个被称为其所有者(owner)的变量,值在任何时候只能有一个所有者。

    2、当所有者离开作用域,这个值将被丢弃。

    3、所有权的转移时零成本的,这里不需要对新的变量开辟一块内存用于存储数据。新变量只是重新分配了资源的所有权。

    例子1:所有权传递(变量)

    fn main(){let x="hello".to_string();//"hello"的所有者为xlet y=x;//"hello"的所有者变为y,这个时候原来的所有者x已失效println!("{}",x);//}

例子2:所有权传递(函数)

    fn create_string() ->String {// 创建并返回一个新的StringString::from("Hell,ownership!")}fn transfer_ownership(s:String) -> String {//返回输入的String,转移所有权s}fn main() {//create_string函数创建了一个值"Hell,ownership!",并将所有权传递给了my_string。let my_string=create_string(); //my_string将值"Hell,ownership!"的所有权传递给了函数transfer_ownership,函数又将所有权传递给了transferred_stringlet transferred_string=transfer_ownership(my_string);//此时my_string已不再对值"Hell,ownership!"拥有所有权。println!("my_string string: {}", my_string); // 此时transferred_string对值"Hell,ownership!"拥有所有权。println!("Transferred string: {}", transferred_string); }

    克隆:

    1、当克隆一个变量时,相当于创建了数据的一个完整副本。

    2、与所有权转移相比,克隆的成本较大,因为涉及到了要内存的使用和数据的复制。

    3、所有权转移后原始变量失效,克隆之后原始变量仍然有效,并且原始变量保留了数据的所有权。这里需要注意,克隆后,两个变量是完全独立的数据实例。

    例子3:

    fn main(){let x="Hello".to_string();//x获取了"Hello"的所有权let y=x.clone();//传递x的副本给yclone_ownership(y);//传递x的副本y给函数clone_ownership//x依然对"Hello"拥有所有权println!("x String:{}",x);//y对"Hello"还拥有所有权吗?不再拥有所有权了,因为已经将所有权传递给了函数clone_ownership// println!("y String:{}",y);}fn clone_ownership(s:String){println!("{}",s);}

    引用:

    1、引用有可变引用(&mut T)和不可变引用(&T)。

    2、可变引用允许修改引用所指向的值,而不可变引用不允许修改引用所指向的值。

    3、为了防止数据竞争,Rust中在任何时间,只能拥有一个可变引用到特定的数据。

    4、由于不可变引用不会改变数据,Rust中可以拥有任意数量的不可变引用。

     例子4:

// 定义一个函数,它接受一个整数的不可变引用
fn print_int(value:&i32)
{// 打印出传入整数的值println!("The value is: {}",value);
}fn  main()
{let _int=11;// 调用函数,传入整数的不可变引用print_int(&_int); 
}

    例子5:

// 定义一个函数,它接受一个整数的可变引用
fn print_int(value:&mut i32)
{// 将整数的值加倍*value *=10; 
}fn  main()
{let mut _int=10;// 调用函数,传入整数的可变引用print_int(&mut _int);// 打印加倍后的整数值println!("The value is :{}",_int);   
}

5、生命周期参数,它可以告诉编辑器,参数的引用和返回值的引用都具有相同的生命周期。例子6中的'a就是生命周期参数

 

    例子6fn return_reference<'a>(data:&'a String)->&'a String{data //返回的引用与输入的引用具有相同的生命周期}fn main(){let external_string=String::from("Hello world");let string_ref=return_reference(&external_string);println!("{}",string_ref);// 这是安全的,因为external_string的生命周期贯穿了整个main函数}
    例子7//定义一个包含引用的结构体,需要生命周期注解struct  Item<'a>{//'a表示引用的生命周期name:&'a str,}// 实现结构体,战术如何使用生命周期impl<'a> Item<'a>{// 创建一个新的Item实例,返回一个带有生命周期的实例fn new(name:&'a str)->Self{Item {name}}}fn main(){let name =String::from("Rust Programming");// 创建一个String类型的变量let item= Item::new(&name);//借用name的引用来创建Item实例println!("Item name:{}",item.name);//打印Item中的name字段}//name的生命周期结束,item.name的引用也不再有效
    例子8fn print_shorter(r:&str){println!("The string is:{}",r);}fn main(){let long_lived_string=String::from("This is a long-lived string.");{let short_lived_str:&str=&long_lived_string;//创建一个常生命周期的引用// 下面的函数调用中,short_lived_str的生命周期会被强制缩短以匹配print_shorterprint_shorter(short_lived_str);}//short_lived_str的生命周期结束//这里long_lived_string仍然有效,因此上面的强制转换是安全的println!("{}",long_lived_string);}
    例子9fn main(){let mut data=vec![1,2,3,4,5];//创建一个不可变引用let data_ref=&data;//打印使用不可变引用的数据println!("Values via immutable reference:{:?}",data_ref);// 下面尝试创建一个可变引用将会失败,因为`data`已经被不可变引用借用let data_mut_ref = &mut data; println!("{}", data_mut_ref);// 这行会导致编译错误,编译错误如下图//下面尝试创建一个可变引用将不会失败// let data_mut_ref=&mut data;// println!("{:?}",data_mut_ref);//只有当不可变引用不再使用后,才能创建可变引用//这里不再使用不可变引用data_ref,因此可以创建可变引用// let data_mut_ref=&mut data;// data_mut_ref.push(6);// println!("Values after mutation:{:?}",data_mut_ref);}

从错误截图上看,只有使用{:?}编译器错误就不存在了。

    例子10:如果有一个或多个不可变引用&T,那么在同一作用域内不能有可变引用&mut T。
如果有一个可变引用&mut T,那么在同一作用域内不能有其他的可变引用或不可变引用&T。
编译器报错提示如下struct MyStruct{value:i32,}//这个函数尝试同时接受一个对象的可变和不可变引用fn example_fn(mutable_ref:&mut MyStruct,immutable_ref:&MyStruct){println!("Mutable reference value:{}",mutable_ref.value);println!("Immutable reference value:{}",immutable_ref);}fn  main() {let mut my_object=MyStruct{value:10};//尝试同时借用可变引用和不可变引用example_fn(&mut my_object, &my_object);}

 

 

    例子11:fn main(){let x=10;//定义一个整数变量xlet y=&x;//创建一个指向x的引用yprintln!("The value of x is:{}",x);//直接打印变量x的值。println!("The address of x is:{:p}",y);//打印引用y的地址,使用{:p}格式化指针地址println!("The value of y is:{}",y);//打印应用y的值,这里会打印出地址  注意这里打印出来的是10而不是地址,不确定是不是Rust版本的问题。println!("The value pointed to by is :{}",*y);//使用解引用操作符来打印y指向的值}
    例子12// 定义一个包含字符串引用的结构体Bookstruct Book<'a>{//'a是一个生命周期注解,表示title的生命周期title:&'a str,}fn main(){let title=String::from("The Rust Programming Language");let book=Book{//title 是一个字符串切片,他引用了title变量的数据title:&title,};println!("Book title:{}",book.title);}
    例子13// longset 函数定义了一个生命周期参数'a,这个生命周期参数制定了输入参数和返回值的生命周期必须相同。fn longset<'a>(x:&'a str,y:&'a str)->&'a str{if x.len()>y.len(){x// 如果x的长度大于y,返回x}else {y //否则,返回y}}fn main(){let string1=String::from("Rust");let string2=String::from("C++");let result=longset(string1.as_str(), string2.as_str());//longset函数比较两个字符串切片的长度println!("The longeset string is {}",result);//注意 result 的生命周期与string1和string2的生命周期相关,因此它们必须在result被使用之前保持有效}
    例子14// 定义一个结构体ImportantExcerpt,它包含一个字符串切片字段partstruct  ImportantExcerpt<'a>{part:&'a str,}fn main(){let novel=String::from("Call me ishmael. Some years ago ...");let first_sentence=novel.split('.').next().expect("Could not find a '.'");let excerpt=ImportantExcerpt{part:first_sentence,};//打印出结构体中的字符串切片println!("Important excerpt:{}",excerpt.part);}
    例子15// 定义一个结构体ImportantExcerpt,它包含一个字符串切片字段partstruct  ImportantExcerpt<'a>    {part:&'a str,}//为ImportantExcept结构体实现方法impl <'a> ImportantExcerpt<'a> {fn announce_and_return_part(&self,announcement:&str)->&str{println!("Attention please:{}",announcement);self.part}}fn main(){let novel=String::from("Call me ishmael. Some years ago ...");let first_sentence=novel.split('.').next().expect("Could not find a '.'");let excerpt=ImportantExcerpt{part:first_sentence,};let announcement="I'm going to tell you something important!";let part=excerpt.announce_and_return_part(announcement);//打印出结构体中的字符串切片println!("Important excerpt:{}",part);  }
    例子16//定义一个拥有静态生命周期的字符串常量static MESSAGE:&'static str="Hello,this is a static lifetime example";fn main(){//打印这个静态生命周期的字符串println!("{}",MESSAGE);}
    例子17//定义一个函数,该函数接收两个引用参数:一个是不带生命周期的引用,另一个是带生命周期的'a的引用fn select<'a>(first:&i32,second:&'a i32)->&'a i32{//这里我们简单地返回第二个参数,它带有生命周期'asecond}fn main(){let num1=10;let num2=20;//创建一个生命周期较长的引用let result;{let num3=num2;//调用函数,num1的引用不带生命周期,num3的引用带有生命周期result=select(&num1, &num3);}//num3的生命周期结束//打印结果,result引用的是num2,因为它与num3共享相同的数据println!("The selected number is {}",result);}
    例子18//定义一个结构体Book,包含一个字符串切片引用,代码书名struct Book<'a>{name:&'a str,}//实现Book结构体的一个方法get_name,返回书名的引用//这里没有显示标注生命周期,因为编译器会自动应用生命周期省略规则impl<'a> Book<'a>{//根据省略规则,这里的返回值生命周期被自动推导问为与&self相同fn get_name(&self)->&str{self.name}    }fn main(){let book=Book{name:"The Rust Programming Language"};//调用get_name方法,打印返回的书名引用println!("Book name:{}",book.get_name());}
例子19
// 定义一个泛型函数`slice_first`,它有一个泛型类型`T`和生命周期`'a`
fn slice_first<'a, T>(data: &'a [T]) -> Option<&'a T> {// 使用`.get()`方法来尝试获取slice的第一个元素的引用// 如果存在,则返回Some(&T),否则返回Nonedata.get(0)
}fn main() {// 创建一个整数类型的slicelet numbers = vec![1, 2, 3, 4, 5];// 调用`slice_first`函数,并打印返回的结果if let Some(first) = slice_first(&numbers) {println!("The first number is {}", first);} else {println!("The slice is empty.");}// 创建一个字符类型的slicelet letters = vec!['a', 'b', 'c', 'd', 'e'];// 同样调用`slice_first`函数,并打印返回的结果if let Some(first) = slice_first(&letters) {println!("The first letter is {}", first);} else {println!("The slice is empty.");}
}

相关文章:

Rust基础语法1

所有权转移&#xff0c;Rust中没有垃圾收集器&#xff0c;使用所有权规则确保内存安全&#xff0c;所有权规则如下&#xff1a; 1、每个值在Rust中都有一个被称为其所有者&#xff08;owner&#xff09;的变量&#xff0c;值在任何时候只能有一个所有者。 2、当所有者离开作用域…...

【算法基础 数学】快速幂

题目描述 给定 n n n组 a i , b i , p i a_i,b_i,p_i ai​,bi​,pi​&#xff0c;对于每组数据&#xff0c;求出 a i b i m o d p i a_i^{b^i}~mod~p_i aibi​ mod pi​ 的值。 样例 输入样例&#xff1a; 2 3 2 5 4 3 9输出样例&#xff1a; 4 1快速幂解决的问题 用来…...

2024年华为OD机考高分攻略-完整题库-两周350分

华为OD是个不错的机会&#xff0c;很适合非软件行业到软件行业的转身。 但是很多同学之前没有软件基础&#xff0c;不知道该如何高效的准备OD机考。 我是一名软件培训老师&#xff0c;我的学生有上百人顺利通过了华为OD机考&#xff0c;并取得了高分&#xff0c;我将经验分享…...

【微信小程序独立开发 4】基本信息编辑

这一节完成基本信息的编辑和保存 首先完成用户头像的获取 头像选择 需要将 button 组件 open-type 的值设置为 chooseAvatar&#xff0c;当用户选择需要使用的头像之后&#xff0c;可以通过 bindchooseavatar 事件回调获取到头像信息的临时路径。 从基础库2.24.4版本起&…...

Docker-基础指令

前置知识 docker官网地址&#xff1a;https://www.docker.com/ docker镜像地址&#xff1a;https://hub.docker.com/ docker安装教程&#xff1a;https://docs.docker.com/engine/install/centos/ 安装只需要注意将仓库源改为国内就好,推荐去阿里云注册自己的账号获得加速地址…...

JUC-Java内存模型JMM

JMM概述 Java Meory Model java内存模型。在不同的硬件和不同的操作系统上&#xff0c;对内存的访问方式是不一样的。这就造成了同一套java代码运行在不同的操作系统上会出问题。JMM就屏蔽掉硬件和操作系统的差异&#xff0c;增加java代码的可移植性。这是一方面。 另一方面JM…...

uni-app使用HBuilderX打包Web项目

非常简单&#xff0c;就是容易忘记 一、找到manifest.json配置Web配置 二、源码视图配置 "h5" : {"template" : "","domain" : "xxx.xx.xx.xxx","publicPath" : "./","devServer" : {&quo…...

前后置、断言、提取变量、数据库操作功能

前置操作和后置操作都是 API 请求在发送和响应过程中执行的脚本&#xff0c;主要用于在发起 API 请求前和获得响应后完成验证或执行某些操作&#xff0c;目的是为了提高 API 调试和测试的效率&#xff0c;并确保接口的正确性。 前置操作​ 前置操作是在 API 请求之前执行的脚本…...

三子棋/井字棋(C语言)

这个游戏需要用到三个文件 game.h头文件用来申明函数和导包 game.h如下: #pragma once #define ROW 3 #define COL 3 #include <stdlib.h> #include <time.h> #include <stdio.h>//初始化棋盘的函数void InitBoard(char board[ROW][COL], int row, int co…...

数据结构小项目----通讯录的实现(这里用链表实现) 超详细~~~~૮(˶ᵔ ᵕ ᵔ˶)ა

目录 Contact.h说明&#xff1a; 结构体与头文件的包含&#xff1a; ​编辑 函数在头文件的声明与定义&#xff1a; Contact.c中各个函数的实现&#xff1a; 1.检查链表中的数据是否满了&#xff0c;满了就扩容 2.链表的尾插 3.链表的删除 4.查找名字是否匹配 5.初始化通讯…...

Electron Apple SignIn 登录

本人写博客&#xff0c;向来主张&#xff1a;代码要完整&#xff0c;代码可运行&#xff0c;文中不留下任何疑惑。 最讨厌写博客&#xff0c;代码只留下片段&#xff0c;文中关键的东西没写清楚。之前看了那么多文章&#xff0c;就是不告诉我clientId从哪来的。 官方资料地址&…...

常用中间件漏洞

IIS6 IIS7 安装 控制面板-----打开关闭windows功能 添加角色-----添加IIS 启动之后访问localhost 复现 服务器换成IIS7 访问报错 大概就是缺少CGI模块 问题解决 添加php-cgi的路径 添加脚本映射 修改php.ini文件 将 cgi.fix_pathinfo1 然后设置一个图片 访问 在后缀加上/.…...

Windows系统使用手册

点击前往查看&#x1f517;我的博客文章目录 Windows系统使用手册 文章目录 Windows系统使用手册Windows10解决大小核调度问题Windows系统安装软件Windows系统Typora快捷键Windows系统压缩包方式安装redisWindows安装dockerWindows系统的docker设置阿里源Windows系统下使用doc…...

mp4文件可以转成mp3音频吗

现在是个非常流行刷短视频一个年代&#xff0c;刷短视似乎成了人们休闲娱乐的一种方式&#xff0c;在日常刷短视频过程中&#xff0c;肯定会有很多同学被短视频 bgm 神曲洗脑&#xff0c;比如很多被网红翻唱带火的歌曲&#xff0c;例如其中"不负人间”&#xff0c;就是其中…...

Java-IO流【登录注册小项目】

♥️作者&#xff1a;白日参商 &#x1f935;‍♂️个人主页&#xff1a;白日参商主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…...

数字化金融时代:探讨全球金融科技创新的最新动态

在当今数字化金融时代&#xff0c;金融科技创新如影随形&#xff0c;迅猛发展。本文将深入探讨全球范围内金融科技的最新动态&#xff0c;剖析各地新兴趋势与突破。从区块链技术的应用到人工智能在金融领域的崭露头角&#xff0c;我们将一一解读这个正在不断演变的金融科技画卷…...

LeetCode:206. 反转链表

力扣链接 算法思想&#xff1a;由于单链表是单向的&#xff0c;想要对当前元素进行操作&#xff0c;需找到前一个元素。本题利用双指针&#xff0c;初始pre指针指向NULL&#xff0c;cur指针指向head.再对局部翻转之前&#xff0c;先把下一个结点存到temp指针中。当进行完如下代…...

linux 安装nginx

介绍 官网 https://nginx.org/en/download.html 在安装nginx前首先要确认系统中安装了gcc、pcre-devel、zlib-devel、openssl-devel linux 检查是否安装过某软件包 yum -y install gcc pcre-devel zlib-devel openssl openssl-devel #下载 wget https://nginx.org/downloa…...

1.C语言——基础知识

C语言基础知识 1.第一个C语言程序2.注释3.标识符4.关键字5.数据类型6.变量7.常量8.运算符9.输入输出输入输出 1.第一个C语言程序 C语言的编程框架 #include <stdio.h> int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }2.注释 单行…...

Redis 存在线程安全问题吗?为什么?

一个工作了 5 年的粉丝私信我。 他说自己准备了半年时间&#xff0c;想如蚂蚁金服&#xff0c;结果第一面就挂了&#xff0c;非常难过。 问题是&#xff1a; “Redis 存在线程安全问题吗&#xff1f;” 一、问题解析 关于这个问题&#xff0c;我从两个方面来回答。 第一个&a…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

【Java_EE】Spring MVC

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

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...