首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【译】Rust与智能指针

C++智能指针原始指针提供了一个安全的替代方案,而 Rust 智能指针则在保证安全的前提下扩展了语言功能。..., a); } 它可以成功运行,但是如果没有注释最后的打印语句会导致编译错误,因为a在当它被赋予b.next的时候被移动(move)了。...如果要把一个对象赋值给另一个 unique pointer,这个指针就必须要被移动(move);所有权被转移并且先前的指针就是无效的了。听起来很熟悉?是的,因为 Rust 的所有权系统也有类似的行为。...为了弥补这一差距,Rust 提供了RefCell——另一种类型的智能指针,该智能指针提供了内部可变性:一种通过借用规则执行推迟到运行时来对不可变引用进行修改。...这是少数几个可以从 Rust 编译器中溜走的 bug。 这意味着在 Rust 中就无法实现双链表了嘛?不,它可以通过另一种称为 weak pointer 的指针来实现。

1K21

第4章 | 移动

笔记 如果不理解Rust底层实现逻辑,只是从JavaScript语言角度来看就很难理解 4.2.1 更多移动类操作 在先前的例子中,我们已经展示了如何初始化工作——在变量进入 let 语句的作用域时为它们提供值...——译者注 如果需要从拥有者中移出一个编译器无法跟踪的值,那么可以考虑拥有者的类型更改为能动态跟踪自己是否有值的类型。...对这些类型进行逐位复制会让我们无法弄清哪个值该对原始资源负责。 那么自定义类型呢?...如果不需要在线程之间共享指针,则没有理由为 Arc 的性能损失“埋单”,因此应该使用 Rc,Rust 能防止你无意间跨越线程边界传递它。...如果这些技术与 Rc 指针结合使用,则确实可以建立循环并造成内存泄漏。 有时可以通过对某些链接使用弱引用指针 std::rc::Weak 来避免建立 Rc 指针循环。

5910
您找到你想要的搜索结果了吗?
是的
没有找到

rust智能指针

智能指针往往是基于结构体实现,它与我们自定义的结构体最大的区别在于它实现了 Deref 和 Drop 特征: Deref 可以让智能指针像引用那样工作,这样你就可以写出同时支持智能指针和引用的代码,例如...*T Drop 允许你指定智能指针超出作用域后自动执行的代码,例如做一些数据清除等收尾工作 Box 堆对象分配 Box 允许你一个值分配到堆上,然后在栈上保留一个智能指针指向堆上的数据。...Box的使用场景 由于 Box 是简单的封装,除了值存储在堆上外,并没有其它性能上的损耗。...,这两个特征可以智能地帮助我们节省使用上的负担:Deref 可以让智能指针像引用那样工作,这样你就可以写出同时支持智能指针和引用的代码,例如 *T。...如果你试图执行 assert_eq!(5, y);,代码就会无情报错,因为你无法一个引用与一个数值做比较。

1.1K30

Rust到底值不值得学--Rust对比、特色和理念

对于有一定经验的常规工程师,他们已经有了一段时间的开发工作实践,对于软件开发的现状、发展都已经形成了自己的世界观。如果感觉并不很喜欢这个行业,希望将来转行管理岗位或者产品岗位。...通过这两个例子,可以看出Rust是从理念上做出了大量创新的一种语言。如果只是像学习其它语言一样只是对比学习语法和关键字,无法真正掌握这门语言。这些融汇在语言中的理念,才是Rust最宝贵的地方。...引用的原始对象必须在引用存在的生命期一直有效 比如: let mut x = 5; let y = &mut x; let z = &mut x; println!...如果把z变量这一行和后面显示z的部分去掉呢?去掉之后是可以编译通过的,但仍然要注意,y此时是可写的指针,“借用”了x的写权限。所以x此时只有读的权限,不能再对x进行赋值。...还有比如,刚才说过了Rust没有析构函数,但如果有一些数据并没有Rust所管理,需要自己去释放,则可以为自己定义的对象实现一个Drop特质,在其中的drop方法中释放自己申请的内存: impl

2.6K30

RUST 语言特性之所有权

RUST 使用包含特定规则的所有权系统来管理内存,这套规则允许编译器在编译过程中执行检查工作,而不会产生任何的运行时开销。这实际上是综合了上面两种内存管理的优势,看起来似乎没有短板。...对于那些在编译期无法确定大小的数据(动态分配,比如根据用户的输入值决定分配多少个数组),只能将它们存储在堆中。 堆空间的管理较为松散:数据放入堆中时,先请求特定大小的空间。...但智能指针存在循环引用的问题,虽然为此又引出了强指针和弱指针来解耦循环引用,但这种解耦依赖于程序员,并没有在语言层面上保证不会循环引用。...所有权与函数 在 C++ 中,指针问题复杂化的一个因素就是各种函数调用与返回,RUST 语言同样如此。 值传递给函数在语义上类似于对变量进行赋值。...变量传递给函数将会触发移动或复制,就像是赋值语句一样。至于何时移动何时复制,和变量类型有关。下面的代码展示了变量在函数传递过程中作用域的变化。

76160

从C++转向Rust需要注意哪些问题?

这也是Rust所谓的内存安全性,即只要没有使用unsafe,编译器可以发现内存的错误访问,并拒绝通过编译。...()} 可以看到,对于返回Option的情形,无法直接Option当作T来处理,只能使用模式匹配机制(match,if let,while let等),T提取出来处理。...相较于使用指针来表达可选情形,Option的表达力会更丰富一些,因为没有强制T转成T*,保留了移动优化的可能性;同时,使用专门的类型来表达可选,在语义上也理加精确一些。...[0,1,2,3,4,5];v.iter().map(|i| println!("{}", i)); 其实并不会去调用println数据输出。...接下来自己争取后面的系列完成。  作者简介 孟杰 腾讯后台开发工程师 腾讯后台开发工程师,毕业于中南大学。目前负责腾讯安全流量分析平台的后台开发工作

85630

Rust 易学教程】第 1 天:Rust 基础,基本语法

易出错的 Rust 函数返回的 Result 值需要拆封,从而检查是否成功。此外,如果没有检查带有 #[must_use]标记的函数的返回值,编译器会发出警告。...编译时验证 编译时的静态内存会进行如下验证: 验证没有未初始化的变量。 验证没有内存泄漏。 验证没有 double-frees。 验证 use-after-free。 验证 NULL 指针。...如果启用,程序陷入奔溃,否则开发者获得环绕语义。默认情况下,将在调试模式(cargo build)和发布模式(cargo build --release)中获得 panic。...像if和while这样的关键词的工作原理是一样的。 变量赋值用=完成,比较用==完成。...除此之外,原始字符串允许开发者创建一个转义值,如: r"\n" == "\\n"。你可以嵌入双引号,在引号的两边加上等量的#: fn main() { println!

28020

Rust 开发命令行工具(上)

如果用户没有提供这些参数,程序将会报错并显示相应的错误消息。 ---- CLI 参数自定义数据类型 与CLI参数视为一堆文本相比,将其视为表示程序输入的自定义数据类型通常更有帮助。...("出错了: {}", error); } } 想了解Rust中枚举和它如何工作的,可以参考Rust枚举和匹配模式。...但它有一个问题:我们没有存储「原始错误,只有它的字符串表示」。...日志 为了更容易理解程序中发生的情况,我们可能想要添加一些日志语句。通常在编写应用程序时这很容易。但在半年后再次运行此程序时,日志变得非常有帮助。「在某种程度上,日志记录与使用 println!...如果你的 Rust 项目使用了日志库,并且在代码中有相应的日志记录语句,那么设置日志级别为 info 会让你看到 info 级别的日志消息。

53740

一起长锈:4 默认不可变的变量绑定与引用(从Java与C++转Rust之旅)

“但是,如果你在声明变量的时候用了mut关键字,那这个变量就可以改变了,很灵活。” 席双嘉:“在C++里是没有这个变量绑定的概念。” 赵可菲:“Java里也没有变量绑定。...那在Rust里就没有变量赋值吗?” 贾克强:“在 Rust 语言中,赋值语句的概念确实还是存在的,但它和变量绑定不一样,两者在用法和含义上有不少区别。”...“赋值语句Rust 中用来修改已经绑定的变量的值。如果变量是可变的,也就是用 mut 声明的,那就可以对其进行重新赋值。” “比如在我们的代码中的这两行。上面一行就是变量绑定,非常简洁。...“RustRust 在编译时强制实行所有权和借用规则,确保不会解引用空指针或悬挂引用。” “如果代码尝试进行不安全的解引用,它将无法编译通过,这样极大地提高了程序的安全性。”...Rust中的解引用操作是通过指针或引用访问或修改其指向的内存中的数据。如果代码尝试进行不安全的解引用,它将无法编译通过,这样极大地提高了程序的安全性。

17543

Rust 让人迷惑的 “借用”

no_takes_ownership(&s), 这里没有直接写 s, 而是取引用 &s 指针与引用 fn main() { let a = 0; let _r = &a; } 上面是最简单的引用例子...可以看到 a 变量分配在栈上 rsp + 0x4, 初始值是 0, 然后第 3 行反汇编可以看到,lea 取了 a 的地址,然后地址传递给栈上的 _r 本质上 rust 引用和普通的指针区别不大,只是在编译阶段...说白了,就是内存谁负责释放的问题 还有一个是类型的方法,第一个参数要写成 &self 或是 &mut self, 如果写成 self 那么函数就会捕捉类型的所有权,函数执行一次,就无法再使用这个类型 struct...同理还有 match 的匹配语句块,也会 move 对像,需要引用 小结 只要我还在更新,就说明没被劝退。在学 rust如果有困惑,一定要记住,所有权,借用与生命周期就是为了保证内存安全。...Go 语言有 GC 可以自动清理垃圾,而 rust 为了零运行时成本,把这一部分工作移到编译期 今天的分享就这些,写文章不容易,如果对大家有所帮助和启发,请大家帮忙点击在看,点赞,分享 三连 关于 Rust

43720

Rust入门之严谨如你

值得注意的是,所有权的所有检查工作,均发生于编译阶段,所以它在运行时没有带来任何额外成本。...当move发生时,“42”这个堆区内存没有发生过拷贝,发生变化的只是y的栈指针指向了“42”这个堆地址,因此它是高效快速的。如果堆区内存非常大时,这种move的效率提升会更加明显。...3.4,不能同时有可变借用与不可变借用 下面展示Rust更严格的一面,不仅不能同时出现两个不可变借用,可变与不可变借用也不能交叉出现,本质还是编译器“担心程序员没有注意到发生了交叉使用”,从而潜在产生...由于Rust默认是保守的,如果在部分场景下程序员能够对代码负责,而Rust无法确认该代码是否安全,这时可以用unsafe关键字包住这段代码,提示编译器这里可以对部分检查进行放行。...4.2,空指针指针的发明者对于这个发明无比懊悔【4】,Rust没有历史包袱,它没有指针。但是Rust依靠枚举和类型检查,提供了一个安全的空指针功能。

1.7K175

Rust学习笔记之并发

其原因在于无法保证线程运行的顺序! 可以通过 thread::spawn 的「返回值储存在变量中来修复新建线程部分没有执行或者完全没有执行的问题」。...send 方法返回一个 Result 类型,所以如果接收端已经被丢弃了,没有发送值的目标,所以发送操作会返回错误。 随后,在主线程中从通道的接收端获取值。...如果线程在等待消息过程中还有其他工作时使用 try_recv 很有用:可以编写一个循环来频繁调用 try_recv,在有可用消息时进行处理,其余时候则处理一会其他工作直到再次检查。...我们会将原始的通道发送端传递给第二个新建线程。这样就「会有两个线程,每个线程向通道的接收端发送不同的消息」。...几乎所有的 Rust 类型都是 Send 的,不过有一些例外,包括 Rc:这是不能 Send 的,因为如果克隆了 Rc 的值并尝试克隆的所有权转移到另一个线程,这两个线程都可能同时更新引用计数

24320

第6章 | 表达式 | 优先级,块与分号,生命,if match

本章探索表达式的强大功能以及如何克服它的局限性。我们介绍在 Rust 中完全面向表达式的控制流,以及 Rust 的基础运算符如何独立工作和组合工作。...= end; ++begin) { if (*begin == target) break; } 表达式有值,而语句没有Rust 是所谓的表达式语言。...这意味着它遵循更古老的传统,可以追溯到 Lisp,在 Lisp 中,表达式能完成所有工作。 在 C 中,if 和 switch 是语句,它们不生成值,也不能在表达式中间使用。...的风格,不会隐式地数值或指针转换为布尔值。...这类似于 switch 语句中的 default: 语句,不过它必须排在最后。 _ 模式放在其他模式之前意味着它会优先于其他模式。这样一来,其他模式永远没机会匹配到(编译器会发出警告)。

7610

Rust入坑指南:智能指针

, x.chars()); } 如果你查看Rc的源码,会发现它并没有实现chars()方法,但我们上面这段代码却可以直接调用,这是因为Rc实现了Deref。...Drop Drop对于智能指针非常重要,它是在智能指针被丢弃时自动执行一些清理工作,这里所说的清理工作并不仅限于释放堆内存,还包括一些释放文件和网络连接等工作。...Rust还为我们提供了另一种智能指针Weak,你可以把它当作是Rc的另一个版本。它提供的引用属于弱引用。它共享的指针没有所有权。但他可以帮助我们有效的避免循环引用。...这里有一点需要注意:Cell中包裹的T必须要实现Copy才能够使用get方法,如果没有实现Copy,则需要使用Cell提供的get_mut方法来返回可变借用,而set方法在任何情况下都可以使用。...由此可见Cell并没有违反借用规则。 对于没有实现Copy的类型,使用Cell还是比较不方便的,还好Rust还提供了RefCell。话不多说,我们直接来看代码。

83230

Rust实战系列-生命周期、所有权和借用

这是一个令人困惑的术语,因为没有值还给所有者。“借用”是为了强调虽然 Rust 中的值只有一个所有者,但是程序的多个部分可以共享对这些值的访问。 1....这是合法的 Rust 代码,但也必须注意所有权问题和生命周期。在没有使用借用的情况下,如果覆盖一个在程序中其他位置仍然会用到的值,编译器会拒绝编译程序。...如果直接代码中使用整数的地方改为结构体,就不能正常工作。 从形式上看,原始类型被称为拥有 Copy 语义,而其他类型拥有 Move 语义。...事实上,值的“所有者”甚至没有对拥有数据的特殊访问权限,也无法阻止程序的其它部分访问。 4. 如何转移所有权 在 Rust 中,有两种方式所有权从一个变量转移到另一个变量。...原始类型(例如:整数)是个很好的例子。对于 CPU 来说,原始类型很容易复制,还不会带来额外开销,在 Rust 中,如果担心所有权被转移的话,可以使用复制。

1.6K20

Rust 中 Trait 的使用及实现分析

比较重要的一点是 trait object 属于 Dynamically Sized Types(DST),在编译期无法确定大小,只能通过指针来间接访问,常见的形式有 Box &dyn...常见问题 向上转型(upcast) 对于 trait SubTrait: Base ,在目前的 Rust 版本中,是无法 &dyn SubTrait 转换到 &dyn Base的。...,该作者通过 transmute trait object 的引用转为两个 usize,并且验证它们是指向数据与函数虚表的指针: use std::mem::transmute; use std:...可以看到,所有 trait 的方法是顺序放在一起,并没有区分方法属于哪个 trait,这样也就导致无法进行 upcast,社区内有 RFC 2765 在追踪这个问题,感兴趣的读者可参考,这里就不讨论解决方案了...这主要因为把一个对象转为 trait object 后,原始类型信息就丢失了,所以这里的 Self 也就无法确定了。 函数中不允许有泛型参数。

1.8K41

第3章 | 基本数据类型 | 字符串类型

字符串字面量的指针类型为 const char *。标准库还提供了一个 std::string 类,用于在运行期动态创建字符串。 Rust 中也有类似的设计。...本节首先展示所有编写字符串字面量的方法,然后介绍 Rust 的两种字符串类型。第 17 章会介绍有关字符串和文本处理的更多信息。...如果字符串的一行以反斜杠结尾,那么就会丢弃其后的换行符和前导空格: println!...\d+)*"); 不能简单地在双引号前面放置一个反斜杠来包含原始字符串——别忘了,前面说过它不识别转义序列。但是,仍有办法解决。可以在原始字符串的开头和结尾添加 # 标记: println!...() 宏的工作方式与 println!() 类似,但它会返回一个新的 String,而不是文本写入标准输出,并且不会在末尾自动添加换行符。 assert_eq!(format!

7810

第3章 | 基本数据类型 | 3.1 固定宽度的述职类型

如果整型字面量没有带类型后缀,那么 Rust 就会延迟确定其类型,直到找出一处足以认定其类型的使用代码,比如存储在特定类型的变量中、传给期待特定类型的函数、与具有特定类型的另一个值进行比较,等等。...最后,如果有多种候选类型,那么 Rust 就会默认使用 i32(如果是候选类型之一的话)。如果无法认定类型,那么 Rust 就会将此歧义报告为错误。...但是,如果没有类型后缀且无法决定类型,那么错误消息可能会令人惊讶。例如,以下代码无法编译: println!...如果第一个语句中 -4_i32 周围没有圆括号,则 -4_i32.abs() 会先针对正值 4 调用 abs 方法,生成正值 4,再根据负号取负,得到 -4。...与整数一样,通常不必在实际代码中写出浮点字面量的类型后缀,但如果你想这么做,那么类型放在字面量或函数上就可以: println!("{}", (2.0_f64).sqrt()); println!

8010

【译】为 嵌入式 C 程序员编写的 Rust 指南

指针 像其他所有的嵌入式语言一样,Rust 也有指针。这些指针通常被称为原始指针,以区别于无数的智能指针类型。RustT 和const T 拼成mut T和const T。...一般来说,原始指针Rust 中只用于指向潜在的未初始化的内存,一般表示地址,而不是实际内存的引用。为此,我们使用引用,这将在后面讨论。 当我们遇到函数时,我们触及到函数指针。...别名 Rust有type,它的工作原理和C语言中的typedef完全一样,其语法为: type MyAlias = u32; 表达式和语句 与C语言非常不同的是,Rust的语法中几乎没有语句:几乎所有的东西都是某种表达式...如果一个块没有以表达式结束(也就是说,里面的每个语句都以分号结束),它将隐式返回(),就像函数一样。...在成功的情况下,返回值是一个包裹着引用的智能指针,其析构器减少原始 RefCell 中的共享/唯一引用计数。换句话说,RefCell 就像一个单线程的读写mutex,没有原子性的代价。

4.6K30
领券