news 2026/4/21 17:04:38

Rust的移动语义

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rust的移动语义

在 Rust 中,默认是移动语义,而不是传统的值传递或引用传递。这是 Rust 最重要的特性之一,理解所有权系统很关键。

  1. 基本规则
fnmain(){lets1=String::from("hello");// s1 拥有字符串lets2=s1;// 所有权从 s1 移动到 s2// println!("{}", s1); // 编译错误!s1 不再有效println!("{}",s2);// 正确:s2 现在拥有字符串}
  1. 函数参数传递

默认是移动(对于有所有权的类型):

fntake_ownership(s:String){// s 进入作用域println!("{}",s);}// s 离开作用域,drop 被调用,内存被释放fnmain(){lets=String::from("hello");take_ownership(s);// s 的所有权移动到函数中// println!("{}", s); // 编译错误!s 不再有效}

使用引用传递(借用):

fnborrow_string(s:&String){// s 是对 String 的引用println!("{}",s);}// s 离开作用域,但因为它不拥有所有权,所以什么也不会发生fnmain(){lets=String::from("hello");borrow_string(&s);// 传递引用,不转移所有权println!("{}",s);// 正确:s 仍然有效}
  1. Copy 类型的值传递

对于实现了 Copy trait 的类型,会自动复制而不是移动:

fncopy_value(x:i32){// i32 实现了 Copyprintln!("{}",x);}fnmain(){letx=5;copy_value(x);// x 被复制到函数中println!("{}",x);// 正确:x 仍然有效}
  1. 不同类型的行为对比
fntest_pass_by(muts:String,n:i32,v:Vec<i32>){s.push_str(" world");println!("函数内: s={}, n={}, v={:?}",s,n,v);}fnmain(){lets=String::from("hello");letn=42;letv=vec![1,2,3];test_pass_by(s,n,v.clone());// s 被移动,n 被复制,v 被克隆// println!("{}", s); // 错误:s 被移动了println!("{}",n);// 正确:n 被复制了println!("{:?}",v);// 正确:使用了 clone()}
  1. 实际示例(字母异位词分组中的所有权处理)
usestd::collections::HashMap;// 版本1:移动所有权fngroup_anagrams_take(strs:Vec<String>)->Vec<Vec<String>>{letmutmap=HashMap::new();forsinstrs{// strs 的所有权被移动到循环中letmutchars:Vec<char>=s.chars().collect();chars.sort();letkey:String=chars.into_iter().collect();// 这里 s 被移动到 map 中map.entry(key).or_insert(Vec::new()).push(s);}map.into_values().collect()}// 版本2:使用引用(借用)fngroup_anagrams_borrow(strs:&[String])->Vec<Vec<String>>{letmutmap=HashMap::new();forsinstrs{// s 是 &Stringletmutchars:Vec<char>=s.chars().collect();chars.sort();letkey:String=chars.into_iter().collect();// 需要克隆字符串,因为 map 需要所有权map.entry(key).or_insert(Vec::new()).push(s.clone());}map.into_values().collect()}// 版本3:使用字符串切片fngroup_anagrams_slice(strs:&[&str])->Vec<Vec<String>>{letmutmap=HashMap::new();for&sinstrs{// s 是 &strletmutchars:Vec<char>=s.chars().collect();chars.sort();letkey:String=chars.into_iter().collect();// 转换为 Stringmap.entry(key).or_insert(Vec::new()).push(s.to_string());}map.into_values().collect()}fnmain(){// 测试版本1letstrs1=vec!["eat".to_string(),"tea".to_string(),"tan".to_string(),];letresult1=group_anagrams_take(strs1);println!("版本1: {:?}",result1);// 测试版本2letstrs2=vec!["eat".to_string(),"tea".to_string(),"tan".to_string(),];letresult2=group_anagrams_borrow(&strs2);println!("版本2: {:?}",result2);println!("原数组仍然可用: {:?}",strs2);// strs2 仍然有效// 测试版本3letstrs3=vec!["eat","tea","tan"];letresult3=group_anagrams_slice(&strs3);println!("版本3: {:?}",result3);}
  1. 所有权在 HashMap 中的体现
usestd::collections::HashMap;fnmain(){letmutmap=HashMap::new();// 插入时移动所有权letkey1=String::from("key1");letvalue1=String::from("value1");map.insert(key1,value1);// key1 和 value1 不再有效// println!("{}", key1); // 错误// println!("{}", value1); // 错误// 获取引用ifletSome(v)=map.get("key1"){println!("值: {}",v);// v 是 &String}// 获取所有权(移除元素)ifletSome(v)=map.remove("key1"){println!("移除的值: {}",v);// v 是 String}}
  1. 性能考虑
fnexpensive_to_clone()->String{"这是一个很长的字符串...".repeat(1000)}fnmain(){lets=expensive_to_clone();// 方法1:移动所有权(高效)fnprocess_owned(data:String){// 处理数据}process_owned(s);// 高效:只是移动指针// 方法2:克隆(低效)lets2=expensive_to_clone();fnprocess_cloned(data:&String)->String{// 如果需要修改并返回,可能需要克隆data.clone()+" modified"}letresult=process_cloned(&s2);// 需要克隆整个字符串// 方法3:修改可变引用(高效)letmuts3=expensive_to_clone();fnprocess_mutable(data:&mutString){data.push_str(" modified");}process_mutable(&muts3);// 高效:不需要克隆}
  1. 总结表格

传递方式 语法 所有权 是否需要 clone 适用场景
移动所有权 func(s: String) 转移 不需要 函数需要拥有数据的所有权
不可变借用 func(s: &String) 不转移 通常不需要 只读访问
可变借用 func(s: &mut String) 不转移 不需要 需要修改数据
克隆 func(s.clone()) 创建新所有权 需要 需要副本同时保留原数据

  1. 在字母异位词分组中的最佳实践
usestd::collections::HashMap;// 最佳实践:根据需求选择合适的传递方式pubfngroup_anagrams(strs:Vec<String>)->Vec<Vec<String>>{// strs 的所有权被移动到函数中// 因为我们需要在 HashMap 中存储这些字符串letmutmap:HashMap<String,Vec<String>>=HashMap::new();forsinstrs{// 移动每个字符串的所有权letkey=sort_string(&s);// 传递引用给辅助函数map.entry(key).or_insert_with(Vec::new).push(s);}map.into_values().collect()}// 辅助函数:只需要读取字符串,不需要所有权fnsort_string(s:&str)->String{letmutchars:Vec<char>=s.chars().collect();chars.sort_unstable();chars.into_iter().collect()}fnmain(){letstrs=vec!["eat".to_string(),"tea".to_string(),"tan".to_string(),"ate".to_string(),"nat".to_string(),"bat".to_string(),];// 调用后,strs 的所有权被转移,不能再使用letresult=group_anagrams(strs);println!("结果: {:?}",result);}

关键点:

  1. Rust 默认是移动语义,不是值传递也不是引用传递
  2. 实现了 Copy trait 的类型会被复制
  3. 使用 & 进行借用(引用传递)
  4. 函数签名决定了所有权如何转移
  5. 在性能敏感的场景,合理使用引用避免不必要的克隆
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 9:07:40

Java毕设项目:基于Java+SpringBoot+Vue的高校大学生心理咨询管理系统基于springboot高校大学生心理咨询管理系统(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/19 3:07:28

FITC荧光标记司美格鲁肽

一、司美格鲁肽基础信息英文名称&#xff1a;Semaglutide中文名称&#xff1a;司美格鲁肽单字母序列&#xff1a;H-Aib-Glu-Gly-Thr-Phe-Thr-Ser-Asp-Val-Ser-Ser-Tyr-Leu-Glu-Gly-Gln-Ala-Ala-Lys-Glu-Phe-Ile-Ala-Trp-Leu-Val-Arg-Gly-Arg-Gly-OH三字母序列&#xff1a;H-His…

作者头像 李华
网站建设 2026/4/19 3:15:20

让Agent系统更聪明之前,先让它能被信任

一、引子&#xff1a;一种“简单”的错觉团队最近常出现一种论调&#xff1a;“现在做 Agent 很简单&#xff0c;用 LangChain、百炼、Flowise 搭一搭就能跑。”这句话乍一听确实无法反驳 —— 框架确实降低了门槛。但那种“简单”&#xff0c;更像是复杂性暂时被平台吸收后的假…

作者头像 李华
网站建设 2026/4/19 3:12:10

开源框架LangChain在教育领域的技术实践指南

开源框架LangChain在教育领域的技术实践指南 【免费下载链接】langchain LangChain是一个由大型语言模型 (LLM) 驱动的应用程序开发框架。。源项目地址&#xff1a;https://github.com/langchain-ai/langchain 项目地址: https://gitcode.com/GitHub_Trending/la/langchain …

作者头像 李华
网站建设 2026/4/21 7:51:04

Wan2.2-T2V-A14B生成视频长度限制是多少?实测告诉你

Wan2.2-T2V-A14B生成视频长度限制是多少&#xff1f;实测告诉你 你有没有试过输入一段特别精彩的描述&#xff0c;满怀期待地按下“生成”按钮&#xff0c;结果只换来一个6秒的小片段——还没看清主角的表情&#xff0c;故事就戛然而止&#xff1f;&#x1f605; 这种感觉&…

作者头像 李华
网站建设 2026/4/18 13:59:38

LMMS开源音乐制作软件:二十年技术演进与创新突破

LMMS开源音乐制作软件&#xff1a;二十年技术演进与创新突破 【免费下载链接】lmms Cross-platform music production software 项目地址: https://gitcode.com/gh_mirrors/lm/lmms 在数字音乐创作的世界里&#xff0c;LMMS&#xff08;Linux MultiMedia Studio&#xf…

作者头像 李华