Rust、Go、C ,哪个才是“内存管理大师”?

Rust入门基础 Rust是一种通用的编程语言,它可以让每个人编写可靠且高效的软件。Rust可以用来替换C/C++,Rust和它们具有同样的性能,但是很多常见的bug在编译时就可以被消灭。Rust能够保证内存安全(无需GC),并且易于维护、调试,代码既安全又高效。 阅读详情

编程语言各有各的“大能”,但如果谈到内存管理,Rust的话语权不是一般的高。GC(垃圾回收)?手动分配?对于掌握了Rust奥义的开发者而言,这些词汇简直弱爆了。众所周知,Rust编程语言的主要卖点之一是它的内存安全性。Rust对待内存,非常有自己的个性。与使用垃圾收集器的编程语言(如Haskell、Ruby和Python)不同,Rust为开发人员提供了快速功能,能够以一种独特的方式高效地使用和管理内存。Rust通过使用借用检查器(borrow checker)、所有权(ownership)、借用(borrow)这三个概念来管理和确保跨堆栈和堆的内存安全来管理内存,从而实现内存管理。本文讨论了Rust借用检查器,Rust与其他语言(如Go和C)的内存管理对比,以及Rust借用检查器的缺点。

内存是如何工作的

在讨论Rust如何管理内存之前,先来回顾一下计算机内存是如何工作的。分配给运行程序的计算机内存分为栈和堆。栈是一种线性数据结构,它按顺序存储局部变量,而不用担心内存的分配和重新分配。每个线程都有自己的栈,当线程停止运行时,每个栈都会被释放。数据以后进先出(LIFO)的模式存储——新的数据堆积在旧数据的上面。堆是一种分层数据结构,用于随机存储全局变量,内存分配和重新分配会是一个需要关注的问题。当一个字面量被压入堆栈时,是会有一个确定的内存位置的;这使得分配和重新分配(入栈和出栈)很容易。但是,在堆上分配内存的随机过程会导致使用内存的开销很大,这使得重新分配内存的速度变慢,因为在堆上分配内存时会涉及到复杂的引用记录。局部变量、函数和方法驻留在栈上,其他所有变量驻留在堆上;因为栈有固定的有限大小。Rust通过在堆栈中存储字面量(整数、布尔值等)来有效地处理内存。像结构体和枚举这些类型的变量在编译时由于没有固定的大小,存储在堆中。

所有权(所有权):“值”的主人

所有权是Rust中的一个概念,用来在没有垃圾收集器的情况下保证内存安全。Rust强制执行以下所有权规则:

  • 每个值都有一个变量,称为owner(所有者)
  • 每个值有且只有一个所有者
  • 如果将变量赋值给新的所有者,那么原始值将被删除,否则它现在就会有两个所有者

在程序编译时,Rust编译器在程序编译之前会检查程序是否遵守了这些所有权规则。如果程序遵循所有权规则,则程序编译执行,否则编译失败。

Rust使用借用检查器(borrow checker)来验证所有权规则。借用检查器验证所有权模型以及内存(堆栈或堆)中的值是否超出范围(scope)。如果值超出范围,则释放内存。但这并不意味着访问值的唯一方法是通过原始所有者。这时就引出了"借用"的概念了。

借用(借用):重用有术

为了允许程序重用代码,Rust提供了借用的概念,和指针类似。

所有权可以暂时从所有者处借用,并在借用变量超出范围时归还。可以通过使用&(&)符号传递对所有者变量的引用来借用值。这在函数中非常有用。下面是一个例子:

1. fn list_vectors(vec: &Vec<i32>) {  
2.     for element in vec {  
3.         println!("{}", element);  
4.     }  
5. }

函数也可以通过使用对变量的可变引用来修改借用变量。普通变量可以通过mut关键字将其设置为可变的,那么可变引用只要在&后添加关键字mut就可以了。当然在进行可变引用之前,变量本身必须是可变的。

1. fn add_element(vec: &mut Vec<i32>) -> &mut Vec<i32> {  
2.     vec.push(4);  
3.   
4.     return vec  
5. }

左右滑动查看完整代码所有权和借用的概念可能看起来没有那么灵活,除非你理解了复制,拷贝,移动的概念,以及它们如何一起工作。

复制所有权

复制通过复制位来复制值。复制仅适用于实现了Copy特征的类型。一些内置类型默认实现Copy特征。在栈中,很容易访问变量并更改所有权,而在堆中复制则不容易,因为位操作涉及位移动和位操作,而栈对于此类操作的组织更有条理。下面是一个在堆中复制值的示例。

1. fn main(){  
2.     let initial = 6;  
3.     let later = initial;  
4.     println!("{}", initial);  
5.     println!("{}", later);  
6.   
7. }

变量initial和later在同一作用域(范围scope)中声明,然后通过赋值将initial的值复制到later中。

虽然变量在相同的范围内,但initial将不再存在。这是在必须重新分配变量的情况下。输出:

图片

试图打印initial变量的值将会引发编译错误,因为借用检查器注意到有变量的所有权转移了。

那如果你想保留这个值呢?Rust提供了克隆变量的能力。

拷贝变量

你可以将值分配给新所有者,同时使用拷贝的方法保留旧所有者中的值。然而,你所拷贝的类型必须提前实现拷贝特征。

1. fn main(){  
2.     let initial = String::from("Showing Ownership ");  
3.     let later = initial.clone();  
4.     println!("{} ==  {} [showing successful cloning] ", initial, later)  
5. }

变量initial在变量later的声明中被拷贝,这两个变量驻留在堆中。如果这时被借用,则这两个变量将引用同一个对象;但是,在这种情况下,这两个变量是堆上的新声明,并占用独立的内存地址。

移动所有权

Rust提供了跨作用域更改变量所有权的功能。当函数按值接受参数时,函数中的变量会成为该值的新所有者。如果你不选择移动所有权,可以通过引用传递参数。下面是一个如何将变量的所有权从一个变量转移到另一个变量的示例。

1. fn change_owner(val: String) {  
2.   
3.     println!("{} was moved from its owner and can now be referenced as val", val)  
4. }  
5.   
6. fn main() {  
7.   
8.     let value = String::from("Change Ownership Example");  
9.     change_owner(value);  
10. }

图片

change_owner函数获得了之前声明的字符串的所有权,并在接受value变量的值作为参数时获得该字符串的所有权。此时试图打印值变量会导致错误。

Rust借用检查器的缺点

如果Rust的借用检查器一切都很完美,那么其他系统编程语言可能会切换或提供带有借用检查器实现的版本。在内存管理的问题上,它是用户体验和便利性之间的权衡。

图片

各主流编程语言的内存管理方案一览

使用垃圾收集器的语言让内存管理变得更容易,但同时也降低了内存管理的灵活性,而像Rust和C这样的语言让开发人员可以快速访问内存,只要遵守它某些规则,如Rust的所有权规则,以及如何在C中将内存管理留给开发人员。

借用检查器可能是复杂的和有限制性的。随着程序规模的增长,自我确保所有权规则可能会变得困难,并且进行更改的代价可能是昂贵的。虽然Rust编译器通过执行检查来防止类似悬空引用这样的错误,但Rust也为开发人员提供了unsafe关键字,可以让指定代码区块不受检查。如果外部使用了依赖项unsafe关键字,这可能不利于代码安全性。许多开发人员,无论是初学者还是专家,都会从借用检查器中碰到所有权错误,更多的错误来自于在Rust中实现复杂的数据结构和算法。

Rust和C的内存管理比较

C编程语言是一种流行的系统编程语言,它不使用垃圾收集器或借用检查器来管理内存;相反,C让开发人员按照自己的意愿手动和动态地管理内存。

C开发人员可以使用在标准库中定义的malloc()、realloc、free和calloc等函数,用于堆中的内存管理,而栈中的内存一旦超出作用域就会自动释放。

哪种方法更好通常取决于要构建的内容。虽然开发人员可能会发现Rust借用检查器有一些限制,但它使开发人员在管理内存时更加高效,而不需要成为内存管理专家。Rust开发人员也可以选择在没有标准库的情况下使用Rust,并获得类似于C语言的体验,其中所有内存管理都是手动来实现。

带有标准库和借用检查器的Rust更适合用于构建需要处理资源密集型的应用程序。

Rust和Go的内存管理比较

Rust和Go是相当新的、强大的语言,经常在许多方面进行比较,包括内存管理。

Go使用非分代并发、三色标记和清除垃圾收集器以一种不同的方式管理内存,允许开发人员使用new和make函数手动分配内存,而垃圾收集器负责内存回收。

Go的垃圾收集由一个执行代码并向堆分配对象的mutator和一个帮助释放内存的收集器组成。Go还允许开发人员通过使用不安全的或者运行时包关闭垃圾收集器来手动访问和管理内存。运行时模块的debug包通过使用SetGCPercent方法(帮助设置垃圾收集器目标百分比)等方法设置垃圾收集器参数,为调试程序提供功能。

Go的垃圾收集器一直以来在接受来自Go开发者社区的批评,并且在过去的几年里一直在改进。Go开发人员可能希望手动管理内存,并能从语言中获得更多,在默认情况下,垃圾收集器不允许像C等语言提供手动内存管理所提供的灵活性。

在讨论内存管理时,Go和Rust是没法比较的,因为它们有不同的、不相关的内存管理方式,在灵活性和内存安全性之间进行权衡,特别是两种语言的开发人员都想要其他语言使用的东西。

开发人员选择Go来构建需要简单性和灵活性的服务和应用程序,选择Rust来构建需要低级别交互,但对性能和内存安全至关重要的应用程序。

借用检查器:Rust人避不开的坎

借用检查器是Rust之旅中不可绕开的困难。学习曲线在这里变得相当陡峭。伴随着借用检查器的接连不断的报错、警告,许多具有Python和JavaScript等语言背景的Rust崇拜者难免怀疑人生:“跟借用检查器硬刚,有前途吗?,还是放弃吧!”

需要明白的是:任何想要绕开借用检查器的想法都是徒劳的。这是一场你永远也赢不了的决斗。唯一能做的,就是将借用检查器看作是教你如何编写内存效率高的Rust代码的纪律制定者,而你必须通过学习更多关于如何编写更安全、内存效率高的Rust代码来玩好跟借用检查器之间的游戏。

随着编写Rust代码量的增加,开发者当然也会像其他语言一样,将找到防止出现借用检查器常见错误的最佳方法。学会与借用检查器斗智斗勇,开发者避无可避。

结语

毫无疑问,Rust是一种会在未来几年存在并被广泛使用的语言。我们已经看到像Discord和Microsoft这样的公司用Rust重写了他们的一些代码库,因为它能够通过外部函数接口(FFI)与C和c++等多种语言进行交互,还有许多其他公司(如AWS、Mozilla等)在产品的不同环节使用Rust。

所有权和借用是Rust中的基本概念,当你编写更多的Rust程序时,你很有可能会从借用检查器中得到一个错误。使用合适的工具是很重要的;你可以考虑在内存管理不是很重要,并且关心性能的程序中使用Go。

rust学习 (一)rustc和cargo rust学习 rustc和cargo 阅读详情

相关推荐

BLAKE3哈希计算性能对比:Rust、C与Go的基准测试与选型指南

哈希函数是计算机科学中用于将任意长度数据映射为固定长度摘要的核心算法,其核心原理是通过特定数学变换确保数据的唯一性与完整性。在密码学与数据校验领域,哈希函数的技术价值在于提供高效的数据指纹生成能力,广泛应用于文件校验、去重、默克尔树构建与区块链等场景。本文聚焦于当前高性能哈希算法BLAKE3,通过设计跨语言基准测试,量化其在Rust、C与Go三种编程语言中的性能表现。测试在严格控制变量的环境下进行,涵盖不同数据规模与并发模式,深入分析了各语言在编译器优化、内存管理及SIMD指令集利用等方面的差异,为分布式存

weixin_33862993的博客 348

Rust语言

Rust 是一门系统级别的编程语言。Rust 由 Graydon Hoare 开发并在被 Mozilla 实验室收购后发扬光大。

m0_72572822的博客 8825

古法编程:在AI时代,为什么底层基本功比框架更重要?

在软件开发领域,对计算机系统原理的深刻理解是构建稳定、高效应用的基石。从内存管理、数据表示到编译链接,掌握这些底层原理能帮助开发者穿透高级语言和框架的抽象,直击问题本质。这种能力在性能优化、框架深度定制、遗留系统维护和资源受限开发等场景中具有不可替代的技术价值。尤其在当前AI辅助编码兴起的背景下,对算法本质、内存布局和问题拆解的深刻认知,成为开发者驾驭工具、做出关键决策和进行终极调试的核心竞争力。本文探讨的“古法编程”理念,正是强调这种不依赖重型工具链、从第一性原理出发解决问题的能力,为开发者在快速更迭的技

weixin_30245867的博客 456

Rust智能指针演进:从堆分配到零复制的内存管理艺术

Rust智能指针系统通过编译期所有权机制与运行时保护,实现了内存安全和零开销的完美平衡。该系统包括:Box<T>用于堆分配、Rc<T>实现共享只读、RefCell<T>提供内部可变性、Arc<T>+Mutex<T>保障线程安全、Weak<T>破解循环引用、Cow<T>优化复制操作。这些智能指针既可组合使用,又能单独应对特定场景,既保留了手动管理内存的性能优势,又通过编译器和运行时检查杜绝了内存安全问题。

技术分享 880

rust教程 第一章 —— 初识rust

本文主要的目的就是认识一下rust这门语言的基本概念

余识- 5万+

Rust助力后端开发,性能飞升新境界

后端开发就像城市的"地下管网系统"——用户看不到它,但每一次App刷新、网页加载、支付转账,都依赖它在背后高效、稳定地运转。传统后端语言各有"独门武功":Java靠"虚拟机+生态"稳坐企业级宝座,Python用"简洁语法+丰富库"横扫数据处理,Go以"原生并发+编译快速"抢占云原生市场。但它们也有各自的"阿喀琉斯之踵":Java的JVM虚拟机像一层"保温棉被",虽然安全却让性能打了折扣;Python的解释执行模式像"步行送货",灵活但遇到大数据量就"气喘吁吁";

架构师的AI之路,分享AI应用开发架构的学习与实践。 1230

程序代码篇---各种编程语言

本文分析了主流编程语言的生态格局,从运行机制、核心定位和应用场景三个维度进行分类解析: 编译型语言(C/C++/Rust)直接生成机器码,以极致性能见长,适用于操作系统、游戏引擎等底层开发; 字节码语言(Java/C#)通过虚拟机运行,平衡性能与跨平台能力,主导企业级应用和游戏开发; 解释型语言(Python/JS)以开发效率取胜,在AI、Web开发等领域占据统治地位。 文章通过对比表呈现各语言在性能、内存管理等维度的差异,指出语言选择应基于具体场景需求。

在你不想做的时候,正是应该做的时候。 309

深入理解C++23的Deducing this特性(上):基础概念与语法详解

C++23标准中引入的"Deducing this"特性是一项重大革新,它不仅改变了我们编写成员函数的方式,还为模板元编程和设计模式实现带来了新的可能。

weixin_61470881的博客 1333

关于编程语言乐子

编程笑话

qq_65379908的博客 424

AMBA VIP基础使用方式(AXI)

AXI环境配置 1)基础配置 作为master或者slave使用时,对应的is_active = 1 只作为i监测(monitor)使用时,对应slave_cfg的is_active = 0(对应端口连接也有所区别) class smu_axi_cfg extends svt_axi_system_configuration; `uvm_object_utils(smu_aix_cfg) function new(string name="smu_axi_cfg); super.new(n..

qq_37573794的博客 7984

MATLABGUI读取文件并将路径显示在文本框中

MATLABGUI读取文件并将路径显示在文本框中

m0_50305149的博客 2650

编程语言设计目的与侧重点全解析(主流语言深度总结)

本文分析了10种代表性编程语言的定位与特性。C语言作为系统编程基石,强调硬件亲和性和极简主义;C++在保持性能的同时引入面向对象与泛型编程;Java通过JVM实现跨平台企业级开发;Python以简洁语法和丰富生态成为通用语言;JavaScript从浏览器扩展到全栈开发;Go语言为云计算设计,突出快速编译和高效并发。这些语言因应不同时代需求和技术场景,形成了各具特色的设计范式,展现了编程语言在效率、抽象度和适用性之间的权衡。

qq_39980997的博客 867

异步复位同步释放:如何确保复位信号的可靠性与时序安全

本文深入探讨了异步复位同步释放技术在数字电路设计中的关键作用,详细分析了复位信号的可靠性与时序安全问题。通过对比异步复位与同步复位的本质区别,揭示异步复位的优势与潜在风险,并提供了标准的Verilog实现方案。文章还涵盖了多时钟域下的复位同步策略、复位网络时序约束方法以及实际工程中的经验教训,为数字系统设计者提供了全面的复位信号处理指南。

weixin_29213655的博客 402

解锁专业模式:如何让你用的AI,写出你不敢想的专业代码(Claude/Cursor/Trae AI等)

摘要:专业提示词(SystemPrompt)能显著提升开发者与AI编程助手的协作效率。通过为AI设定特定技术领域的专家角色(如"C++专家"或"Elixir/OTP专家"),可使AI输出符合该领域最佳实践的代码,减少基础规范修正时间。使用方法是:1)获取目标技术栈的专业提示词;2)将其置入AI工具的系统指令;3)在专家角色上下文中展开对话。这种方式让开发者能在不同技术场景中快速切换AI的专业身份,实现深度技术协作。

zzcoding 750

全网最全-DA14531-全球最小-BLE从入门到精通开发教程

本教程主要适用于低功耗产品,DA14531它体积小,非常适用于对体积敏感的设备,如无线可穿戴、传感器、助听器等设备。本文经过作者发大量时间来记录开发项目的调试方法,里面有许多笔者开发心得体会,旨在让读者工程师快速上手,减少摸索时间,提高软件质量。读者对象本文档主要适用以下工程师:嵌入式系统工程师单片机软件工程师IOT固件工程师BLE固件工程师。

hejinwu1314的博客 5138

2025国赛数学建模A题 完整Python代码 烟幕干扰弹的投放策略

常量定义G = 9.8 # 重力加速度 m/s²V_SMOKE_SINK = 3 # 烟幕下沉速度 m/sMISSILE_SPEED = 300 # 导弹速度 m/sEFFECTIVE_RADIUS = 10 # 有效遮蔽半径 mEFFECTIVE_DURATION = 20 # 有效遮蔽时间 sTARGET_POS = np.array([0, 200, 0]) # 目标位置FALSE_TARGET_POS = np.array([0, 0, 0]) # 假目标位置# 初始位置。

YOLO 1106

如何从零构建任何技术:终极编程学习指南

在编程学习的道路上,你是否曾想过"如果能从零开始构建一个数据库、操作系统或编译器,那该多好"?这正是build-your-own-x项目的核心理念。这个开源项目汇集了从零开始构建各种技术栈的完整指南,帮助开发者通过实践深入理解计算机科学的底层原理。无论你是想掌握分布式系统、数据库实现,还是想了解操作系统内核,这里都有详细的教程和资源。 ## 🚀 为什么选择"从零构建"的学习方式? 传统的编程

gitblog_00524的博客 228

uniapp - 超详细实现播放 svg / svga 格式动画组件插件,用于直播间赠送礼物特效动画或项目动画特效较多的应用(新手小白保姆级教程,提供插件+详细运行示例+使用文档+注意事项+格式说明)

uniappsvga,uniapp播放svga动画,uniapp中使用svga动画详细教程,uniapp播放svga的插件,uniapp有没有调用svga格式动画的组件插件,uinappH5App小程序全端兼容的svga播放器免费好用插件,uniapp好用的svga格式动画插件,在uniapp中使用SVGAPlayer播放svga动画,uniapp中使用svga动画,编译到apph5,uniapp运行svg动画,uniapp怎么使用svga文件格式,uniapp播放svg格式的动画教程,un

🏆 前端领域优质创作者 1万+

Python开发者如何选择第二编程语言提升竞争力

在软件开发领域,多语言编程能力正成为开发者职业发展的关键因素。从技术原理来看,不同编程语言在性能特性、内存管理和并发模型等方面存在显著差异。Python虽然在快速开发和数据科学领域表现出色,但在性能敏感场景如高频交易、嵌入式系统等存在局限。掌握Go、Rust等系统级语言可以显著提升计算效率,其中Go的协程机制可实现百万级并发,Rust的所有权系统则能在保证内存安全的同时达到C++级别的性能。从工程实践角度,多语言技术栈在云计算、数据流水线等场景具有重要价值,例如使用Rust加速Python性能瓶颈可获得40

weixin_32520095的博客 227

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

无名杀 上手指南:3分钟本地部署开源网页版三国杀

无名杀是一个开源的网页版三国杀,打开浏览器就能玩,不需要安装任何客户端。本文带你在3步内从克隆仓库到启动联机大厅,并讲清楚武将、卡牌、主题分别在哪个目录改。项目自带1600多个武将的数据和12种游戏模式,身份局、国战、1v1、欢乐成双都能开。 ## 功能速览 - 打12种游戏模式:身份局、国战、1v1、欢乐成双之外,还有斗地主、五子棋、斗兽棋等10种 - 选1600多名武将:`characte

gitblog_00802的博客 393

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

算法实战宝典:50个核心代码实现带你掌握数据结构与算法精髓

你是否曾为面试中的算法题而苦恼?是否在项目中遇到性能瓶颈却不知如何优化?GitHub加速计划中的alg/algo项目为你提供了终极解决方案——50个精心设计的数据结构与算法代码实现,涵盖从基础到实战的完整学习路径。这个多语言算法库通过C/C++、Java、Python、Go等10余种编程语言的实现,帮助开发者系统掌握算法核心原理与实战技能,让你的编程能力实现质的飞跃。 ## 🚀 从理论到实战:

gitblog_00174的博客 1139

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

程序员内功修炼:数学、算法与数据结构、高级语言原理三大底层支柱

在软件开发领域,算法与数据结构是构建高效程序的核心基础,它们决定了代码的执行效率和资源消耗。从哈希表、链表到树与图,不同的数据结构对应着不同的数据组织与访问模式,而算法复杂度分析(大O表示法)则为性能评估提供了数学工具。理解这些底层原理,能帮助开发者在设计阶段就预判性能瓶颈,写出更优雅、高效的代码。高级语言如Python、Java等通过编译、解释、内存管理和类型系统等机制,将人类可读的代码转化为机器指令,其中自动垃圾回收(GC)和并发模型(如多线程、协程)是工程实践中的关键考量。掌握这些基础,不仅能优化缓存

weixin_30924087的博客 871
上一篇: 解读最常见的 Wi-Fi 标准和类型
下一篇: ChatGPT无法胜任的五种编程任务
老贾的AI世界
博客等级 码龄7年 3335粉丝 254原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老贾的AI世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值