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

【翻译】Rust生命周期常见误区

误解推论 避免使用泛型生命周期是可能的 这种安慰性的误解的存在是由于Rust的生命周期省略规则, 这些规则让你能够在函数中省略生命周期记号, 因为Rust的借用检查器能根据以下规则将它们推导出来:...Rust同样有着对于trait对象的生命周期省略规则,它们是: 如果一个trait对象作为一个类型参数传递到泛型,那么它的生命约束会它包含的类型推断 如果包含的类型中有唯一的约束,那么就使用这个约束...,那么它的生命周期将会表达式推断,如果不在表达式,那么就是 'static 的 这么多东西听起来超级复杂,但我们可以简单地总结为 "trait对象的生命周期约束是从上下文中推断出来的。"...// 将self的可变引用降级为T的共享引用 fn other_method(&mut self) -> &T; } 即使你避免了函数方法签名的重新借用,Rust仍然会自动隐式重新借用...要点 尽量不要把可变引用重新借用为共享引用,不然你会遇到不少麻烦 重新借用一个可变引用不会使得它的生命周期终结,即使这个可变引用已经析构 10) 闭包遵循函数相同的生命周期省略规则 比起误解,这更像是

1.6K20

go 开发者的 rust 入门

切片(slice)类型是对一个数组的引用片段, 这点所有权相关 字符串类型 str,通常是以不可变借用的形式存在,即&str 表达字符串可以用 str, String, CStr, CString...[image] 引用与借用 & 符号就是 引用,它们允许你使用值但不获取其所有权 获取引用作为函数参数称为 借用(borrowing) 规则如下: 不允许修改借用引用的值 可变引用允许修改,但是定作用域中的特定数据只能有一个可变引用...可以避免数据竞争(data race) 也不能在拥有不可变引用的同时拥有可变引用 一个引用的作用域声明的地方开始一直持续到最后一次使用为止 即:在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用...生命周期并不总是指明,省略规则如下【规则会变化,生命周期的规则在 rust 的进化过程会不断打补丁】: 每一个在输入位置省略生命周期都将成为一个不同的生命周期参数。...即对应一个唯一的生命周期参数。 如果只有一个输入的生命周期位置(无论省略还是没省略),则该生命周期都将分配给输出生命周期

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

    第5章 | 对值的引用,使用引用,引用安全

    迭代HashMap 的共享引用就是对每个条目的键值的共享引用:artist String 变成了 &String,而 works Vec 变成了 &Vec...[1973, 1968]; v.sort(); // 隐式借用对v的可变引用 (&mut v).sort(); // 等效,但是更烦琐 简而言之,C++ 会在引用左值(引用内存位置的表达式...变量 r x 都有各自的生命周期它们被初始化的时间点一直延续到足以让编译器断定不再使用它们的时间点。第三个生命周期是引用类型,即借用了 x 并存储在 r 的引用类型。...实际上,Rust 的早期版本就是这么做的,但开发人员发现这样会令人困惑:了解“某个值是另一个值借用出来的”这一点很有帮助,特别是在处理错误时。...,本质上都是 self 借用的。

    9510

    第5章 | 共享与可变,应对复杂关系

    这种结构不能存在对任何内容的有效可变引用,其拥有者应保持只读状态,等等。值完全冻结了。 可变访问是独占访问。 可变引用借用的值只能通过该引用访问。...在可变引用的整个生命周期中,无论是它的引用目标,还是该引用目标间接访问的任何目标,都没有任何其他路径可访问。对可变引用来说,唯一能自己的生命周期重叠的引用就是可变引用本身借出的引用。...但是 Rust 也可以将我们的错误视为违反了第一条规则:因为我们借用了对 wave 元素的共享引用,所以这些元素 Vec 本身都是只读的。不能对只读值借用可变引用。...; // 正确: 可变引用借入可变引用 *m0 = 137; let r1 = &m.1; // 正确: 可变引用借入共享引用,并且不能m0重叠 v.1;...Rust 到处都在应用这些规则:如果要借用HashMap 中键的共享引用,那么在共享引用的生命周期结束之前就不能再借入对 HashMap可变引用。

    10210

    Rust 总结

    借用/引用获取变量的引用。允许使用值但不获取其所有权。像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。包括可变引用可变引用。可变引用同时只能存在一个。...注意,引用的作用域 s 创建开始,一直持续到它最后一次使用的地方,这个跟变量的作用域有所不同,变量的作用域创建持续到某一个花括号 }。3 生命周期生命周期,是引用的有效作用域。...在实际开发,Cell 使用的并不多,因为我们要解决的往往是可变、不可变引用共存导致的问题,此时就需要借助于 RefCell 来达成目的。对于引用 Box,借用规则的不可变性作用于编译时。...RefCell 记录当前有多少个活动的 Ref RefMut 智能指针。像编译时借用规则一样,RefCell 在任何时候只允许有多个不可变借用或一个可变借用。...一个常见的、错误的使用 RwLock 的场景就是使用 HashMap 进行简单读写,因为 HashMap 的读写都非常快,RwLock 的复杂实现相对低的性能反而会导致整体性能的降低,因此一般来说更适合使用

    1.7K30

    Rust 概念解惑 | Deref vs AsRef vs Borrow vs Cow

    比如Add trait 对应的就是 +,而 Deref trait 则对应 共享(不可变借用 的解引用操作,比如 *v。相应的,也有 DerefMut trait,对应独占(可变借用的解引用操作。...因为 Rust 所有权语义是贯穿整个语言特性,所以 拥有(Owner)/不可变借用(&T)/可变借用(&mut T)的语义 都是配套出现的。...其实在标准库文档给出的 HashMap 示例已经说明的很好了。我来给大家翻译一下。...Borrow 是对借用数据的一种限制,并且配合额外的trait来使用,比如示例的 Hash Eq 等。 再看一个示例: // 这个结构体能不能作为 HashMap 的 key?...有点类似于 Option,表示两种情况的某一种。Cow 在这里就是表示 借用 自有的,但只能出现其中的一种情况。

    3.3K30

    听GPT 讲Rust源代码--compiler(40)

    借用检查是Rust的一项重要特性,它保证了在编译时不会出现数据竞争空指针异常等问题。在Rust,当一个值被借用时,它将被认为是不可变的(immutable)或可变的(mutable)。...在可变借用的情况下,不允许同时存在其他的可变借用或不可变借用,因为这可能导致数据竞争。 rustc_borrowck模块是Rust编译器负责借用检查的部分。...这些函数会分析程序借用所有权的使用方式,检查是否存在悬垂指针、重叠借用、不可变借用可变借用冲突等问题,并生成相应的错误或警告信息,以帮助开发者修复代码的潜在问题。...该文件的主要结构功能如下: UseFactsExtractor结构体:这是一个提取借用使用事实的辅助结构体。它包含一些方法字段,用于类型检查中提取数据用于生成活性信息。...它包含了一个借用关系图查询推断出的活性信息。 这些结构体功能共同实现了Polonius项目的借用检查器的核心功能,包括借用使用事实的提取、区域推断活性信息的生成。

    8510

    Rust语法入门

    然后我们访问了数组的元素,并使用 for 循环遍历了数组的每个元素。请注意,在 Rust ,数组的索引0开始,而不是1开始。...在函数签名,我们使用了生命周期参数'a来表明xy参数的生命周期与返回值的生命周期是相同的。...通过使用生命周期,我们可以在Rust管理内存分配释放的方式,以确保安全正确的内存使用。...在上面的示例,我们使用生命周期'a来表明longest函数返回的引用是xy参数的引用之一,以便编译器可以检查引用的有效性生命周期的正确性。...比如: fn foo(x: &i32) { // ... } let x = 42; foo(&x); // 传递不可变引用 在函数参数传递引用时,函数不会获取所有权,而是只能使用借用的值。

    1.2K30

    Rust编程学习笔记Day6 Borrow的生命周期及约束规则

    借用生命周期及其约束 所以在对值的引用也要有约束:借用不能超过值的生存周期。什么意思呢? 说人话就是,生命周期短的可以借用生命周期长的,生命周期长的不能借用短的。...有些情况我们需要在借用的过程修改值的内容,这就需要用到可变借用 可变借用 在没有引入可变借用之前,因为一个值同一时刻只有一个所有者,所以如果要修改这个值,只能通过唯一的所有者进行。...() 方法 是 &mut,已经可变借用一次;然后在 {} ,data.push() 方法 还是 &mut, 在第一次 &mut 期间,又 一次 &mut,在同一作用域下,多个可变引用,这是不合法的。...可变引用的约束我们可以看到,Rust 不但解决了 GC 可以解决的内存安全问题,还解决了 GC 无法解决的问题。...一个值可以有唯一一个活跃的可变引用。可变引用(写)只读引用(读)是互斥的关系,就像并发下数据的读写互斥那样。 引用的生命周期不能超出值的生命周期

    36610

    掌握Rust:从零开始的所有权之旅

    作用域销毁 借用 修改 可变借用 所有权原则 内部可变生命周期 总结 移动?拷贝? 先来试试常规的赋值语句在Rust有什么样的表现 println!...所有权可转移 借用可变借用可以有多个 可变借用同一时间只能有一个 这些规则,规范了对于一个变量谁持有,离开作用域是否可以释放,变量的修改借用有什么样要求,避免释放后的内存被借用,也防止修改读取的内容不一致有...如果入参出参都是一个生命周期,即出参的借用在入参的借用作用域内,只要入参的生命周期合法,那出参的就是合法的。...最后我们看下下边编译不通过的代码,编译期的报错你就应该能明白,为什么要生命周期标注了,它对于让编译期做借用的作用域合法性检查很有用。...借用检查器在编译时保证借用的有效性安全性 生命周期关注的是借用的有效范围引用的合法性 他们配合在一起,构建起了Rust强大的内存管理能力。

    30140

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

    借用检查器依赖于三个相互关联的概念:生命周期、所有权借用生命周期 值的生命周期是指访问该值有效的时间段。...Rust 的每个值都是所有权,在上面的示例代码,sat_a,sat_b sat_c 都“拥有”它们引用的数据,当调用 check_status() 时,数据的所有权 main() 函数范围内的变量转移到...这是合法的 Rust 代码,但也必须注意所有权问题生命周期。在没有使用借用的情况下,如果覆盖一个在程序其他位置仍然会用到的值,编译器会拒绝编译程序。...接受者 to 是对 CubeSat 实例的可变借用(&mut,需要修改 to mailbox.message 的值 ),msg 对其 Message 实例有完全的所有权(函数返回时生命周期结束) Messag...实例的所有权 msg 转移到 messages.push() 的局部变量 注意,GroundStation.send() CubeSat.recv() 都需要对 CubeSat 实例的可变访问,

    1.7K20

    Rust学习笔记Day11 类型系统及多态是如何实现的?

    内存的角度看,类型安全是指代码,只能按照规定的方法,访问被授权的内存。以下图为例,一个类型为u64,长度是4的数组。 数据类型 Rust里的数据类型分为原生类型组合类型。... = HashMap::new(); HashSet 集合 let set:HashSet=HashSet::new(); RefCell 为T提供内部可变性的智能指针 let...---- 在 Rust 里,生命周期标注也是泛型的一部分,一个生命周期 'a 代表任意的生命周期 T 代表任意类型是一样的。...Sized代表可变大小的类型。 符合ToOwned trait:ToOwned 是一个 trait,它可以把借用的数据克隆出一个拥有所有权的数据。...上面 Vec Cow 的例子,泛型参数的约束都发生在开头 struct 或者 enum 的定义,其实,很多时候,我们也可以 在不同的实现下逐步添加约束 泛型函数 现在知道泛型数据结构如何定义使用了

    1K20

    rust的vectorhashmap

    还有一点需要注意,上例的a是可变变量,而b是不可变变量。因此无法使用b.push来追加元素。 向数组末尾追加元素 使用push方法可以向数组末尾增加元素。需要确保数组变量是可变变量。...例如: let mut a = Vec::new(); a.push(1); Vector读取元素 读取指定位置的元素有两种方式可选: 通过下标索引访问,直接获取元素值 使用 get 方法,获取到Option..., } } 其它语言一样,集合类型的索引下标都是 0 开始,&v[2] 表示借用 v 的第三个元素。如果存在下标越界的可能,那么建议使用get来获取元素,否则还是使用下标的方式会更好。...重提内存安全 让我们首先来回顾一下rust的所有权系统以及引用(借用)。 所有权系统 Rust 的每一个值都有一个 所有者(owner)。 值在任一时刻有且只有一个所有者。...引用规则 同一作用域,一个变量只能有一个可变引用; 在同一作用域,一个变量可以有多个不可变引用,不允许同时存在可变引用可变引用。 现在,让我们直接看下面这段代码。

    51230

    Rust编程学习笔记Day7-一个值可以有多个所有者吗?

    Box是Rust的智能指针,可以强制吧数据创建在堆上,然后在栈上用一个指针指向这个数据结构,但这时候堆内存的生命周期是可控的,跟栈上的指针保持一致。...但是Box::leak可以堆上泄露出去,不受栈内存的控制,是一个自由的、生命周期可以大到整个进程一样的对象。有点类似C/C++里的malloc()分配的内存。...搞明白了 Rc,我们就进一步理解 Rust 是如何进行所有权的静态检查动态检查了: 静态检查,靠编译器保证代码符合所有权规则; 动态检查,通过 Box::leak 让堆内存拥有不受限的生命周期,然后在运行过程...注意:这里在可变借用的时候用一对{},这是因为使用 {} 缩短可变借用生命周期。...在同一个作用域下,不能同时拥有可变借用(borrow_mut)可变借用(borrow) 这就是外部可变内部可变性的重要区别,我们用下表来总结一下: 使用方法 所有权检查 外部可变性 let mut

    94430

    Rust 提升安全性的方式

    C++ 不同,Rust 默认是不可变的,这包括了变量默认不可变借用也是默认不可变的,所以以下代码是非法的: fn foo(v: &Vec) { // error: cannot...const 来表示不可变不同,在 Rust ,我们需要手动添加 mut 关键字才能表达可变,这包括了变量声明借用声明的地方,所以下面的代码可以编译通过: fn foo(v: &mut Vec<i32...("{}", add(&x, &x)) } 上面这段代码,i1 i2 都被标记为不可变借用,所以,对变量 x 同时进行这两个借用是合法的。...如果在 Rust ,这个错误则直接可以被 Borrow Checker 发现,它将禁止用户同时对 vec 进行可变可变借用。...Lifetime 是 Rust 另一个重要的概念 9,一个变量初始化到最终销毁构成了其生命周期

    95920

    实现一个线程安全且迭代器可以保存的链表

    一个重要的原因是 std::collections::LinkedList 也遵循 Rust 的借用可变借用的规则,另一方面也是由于它的实现是尽可能没有额外开销。...Rust 是在编译期去分析管理对象的生命周期的,所有对象的生命周期的持有者只能有一个。所有对象都只能有一个可变借用或多个不可变借用。但是可变借用多个不可变借用直接不能共存,相当于是编译期的读写锁。...借用可以理解为不管理生命周期的引用。 稳定版本的 std::collections::LinkedList 的迭代器 Iter IterMut 是没有插入删除接口的。...比如说,如果使用 cursor_front_mut(&mut self) 函数创建一个可变的 CursorMut。那么会占用掉容器的可变借用的权限。...新链表的结构 另一个角度说,我们需要的是能够保存迭代器,并在需要的时候基于迭代器操作。这本身是一个运行时可以修改容器的行为,属于运行时可变借用

    1.2K20

    Rust学习:如何解读函数签名?

    但实际上,这些可能的解决方案都没有解决真正的问题:我们想同一只狗一起走路玩耍! 借用 我可以借你的狗吗? 代替将我们的Dog移动到walk_dog()函数,我们只想借用我们的Dog到函数。...你可以将一个不可变借用传递给任意数量的对象,而可变借用一次只能传递给一个对象。这确保了数据的安全性。 所以我们新的借用功能并没有真正解决问题,不是吗?我们甚至不能改变狗!让我们试着看看错误信息。...内置trait 如果你在trait实现函数,你可以访问以下两个“元素”: Self,类型,表示当前类型。 self,参数,指定结构体实例的借用/移动/可变性。...在下面的walk(),我们采取可变借用,self移动值。...基本上这个函数签名是说:调用Option的生命周期与返回的[T]的生命周期相同。 挑战时间 下面,你将看到标准库中提取的一组函数以及指向其文档的链接。你能从他们的函数签名中看出他们做了什么吗?

    2.1K40

    实现一个线程安全且迭代器可以保存的链表

    一个重要的原因是 std::collections::LinkedList 也遵循 Rust 的借用可变借用的规则,另一方面也是由于它的实现是尽可能没有额外开销。...Rust 是在编译期去分析管理对象的生命周期的,所有对象的生命周期的持有者只能有一个。所有对象都只能有一个可变借用或多个不可变借用。但是可变借用多个不可变借用直接不能共存,相当于是编译期的读写锁。...借用可以理解为不管理生命周期的引用。 稳定版本的 std::collections::LinkedList 的迭代器 Iter IterMut 是没有插入删除接口的。...新链表的结构 另一个角度说,我们需要的是能够保存迭代器,并在需要的时候基于迭代器操作。这本身是一个运行时可以修改容器的行为,属于运行时可变借用。...但是我们这里分离了迭代器容器的生命周期,就不能简单地这么声明了。 首先,由于我需要让这个链表的迭代器容器的生命周期解绑,所以对链表的节点包了一层 Arc 。

    66520
    领券