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

网站策划设计网页免费模板大全

网站策划设计,网页免费模板大全,西宁市建设网站公司电话,电源 东莞网站建设Rust因在内存管理上的独到之处#xff0c;近年来受到了不少开发者的青睐。Rust内存管理的核心功能就是所有权。不同的语言采取了不同的内存管理方式#xff0c;主要分为开发者手动管理或者编译器辅助管理#xff0c;以及垃圾回收机制等。Rust的所有权机制#xff0c;有别于…Rust因在内存管理上的独到之处近年来受到了不少开发者的青睐。Rust内存管理的核心功能就是所有权。不同的语言采取了不同的内存管理方式主要分为开发者手动管理或者编译器辅助管理以及垃圾回收机制等。Rust的所有权机制有别于这两者。 堆栈内存 我们知道程序会在堆或者栈上创建数据。栈上创建数据很容易只要知道数据的大小移动栈顶指针就能开辟出所需要的空间。对它的访问代码层面我们有变量汇编层面只是一个相对于栈顶地址的偏移而已这个偏移量往往很小所以访问栈数据很快。而堆上创建数据则比较麻烦我们要从内存空间寻找一块合适大小的内存然后“开辟”出来也就是需要登记下哪一块空间被使用了。然后需要存储这个地址的开始地址占用大小实际使用大小等。访问这块内存的话也要根据记录的开始地址去内存空间里寻址这个过程相对比较慢。 我们使用堆内存是因为它有一些栈内存没有的好处1.可以动态开辟。栈中的所有数据都必须占用已知且固定的大小。我们在编译阶段已经能知道栈上的变量的相对位置关系和大小。而我们可以根据需要开辟任意允许大小的堆上数据。开辟的这些数据我们也无法确定它们之间的位置关系。2.堆内存可以共享。因为指针和实际内存的分离使得我们可以使多个指针指向同一块内存来实现数据共享。但是因为栈变量即栈内存所以两个变量也就意味着两份存储。3.可以操控的生命周期。一旦发生清栈栈上开辟的内存就会被销毁。而堆上的内存可以存在很久有些语言里需要开发者手动清除有一些需要一些回收机制来清理。 所有权规则 我们先提出Rust的所有权规则 Rust 中的每一个值都有一个 所有者owner。值在任一时刻有且只有一个所有者。当所有者变量离开作用域这个值将被丢弃。 这里的作用域指的是变量的有效使用范围。基于我们前面对堆栈的认识我们发现栈上的变量是符合上述描述的。栈变量即栈内存变量既是值的唯一所有者当我们离开变量的作用域编译器不允许我们再次使用这个变量此时它已经被丢弃后续清栈的时候它就会被销毁。但是对于堆内存上述规则在C、C等语言里就不符合了。有些语言通过在变量作用域结束的地方插入释放变量所指内存的代码来实现内存管理。但是如果有多个指针指向同一个内存就存在多次释放的问题。于是有的语言就使用了引用计数的技术每个指针变量都是内存的所有者。变量离开作用域的时候只减少引用计数并不立即执行释放内存的操作。待等到引用计数降为0的时候才释放内存。Rust则从源头控制任意时刻只有一个所有者这样所有者离开作用域就能立即丢弃这个值。 变量与数据交互方式 那如何确保上述规则呢这里就要提到变量与数据交互的几种方式移动、克隆、引用借用。 移动是Rust语言有别于其他语言的一种行为。在C/C中我们多个指针变量可以指向同一块内存可以对任意一个调用free或者delete。但是Rust中为了确保唯一所有者这个规则当你用另一个变量指向当前变量指向的内存时它认为你后续不会再使用前面这个变量了也就是把所有权转移给另一个变量了。 如果你要保持当前指针的有效其中的一个办法就是克隆一块新的内存这样两块内存两个所有者就没有违反上述规则了。对于堆内存而言通常需要调用clone方法。对于栈内存而言类似int之类的编译时已知大小的类型拷贝往往是自动发生的。而一些特殊的自定义类型需要实现Copy trait。 但是克隆大内存往往会产生比较大的消耗而且往往我们并不需要一块新的内存。我们能不能在不转移所有权的情况下用其他变量去借用一下这块内存有这就是引用。引用很好既没有转移所有权也没有增加所有者。但是引用引入了新的问题。 引用 数据竞争 引用给了我们用其他变量访问同一块内存的能力而且不会转移所有权这很棒但是默认情况下引用只能读取值而不能修改值。除非你声明一个可变引用 fn main() {let mut s String::from(hello);change(mut s); }fn change(some_string: mut String) {some_string.push_str(, world); }现在有了能读能写的引用看起来一切很美好但是这就引入了读写竞争问题。 数据竞争data race类似于竞态条件它可由这三个行为造成 两个或更多指针同时访问同一数据。至少有一个指针被用来写入数据。没有同步数据访问的机制。 不可变引用的用户可不希望在他们的眼皮底下值就被意外的改变了然而多个不可变引用是可以的因为没有哪个只能读取数据的人有能力影响其他人读取到的数据。所以两个可变引用、一个可变引用多个不可变引用都不能在生命周期内发生重叠否则编译器会报错。 悬垂引用 在具有指针的语言中很容易通过释放内存时保留指向它的指针而错误地生成一个 悬垂指针dangling pointer所谓悬垂指针是其指向的内存可能已经被分配给其它持有者。相比之下在 Rust 中编译器确保引用永远也不会变成悬垂状态当你拥有一些数据的引用编译器确保数据不会在其引用之前离开作用域。Rust通过检查所有者的生命周期来确保引用的有效性。 生命周期注解 生命周期的主要目标是避免悬垂引用大部分时候生命周期是隐含并可以推断的但也会出现引用的生命周期以一些不同方式相关联的情况所以 Rust 需要我们使用泛型生命周期参数来注明他们的关系这样就能确保运行时实际使用的引用绝对是有效的。来看一个例子 fn main() {let string1 String::from(abcd);let string2 xyz;let result longest(string1.as_str(), string2);println!(The longest string is {}, result); }fn longest(x: str, y: str) - str {if x.len() y.len() {x} else {y} }当我们定义这个函数的时候并不知道传递给函数的具体值所以也不知道到底是 if 还是 else 会被执行。我们也不知道传入的引用的具体生命周期所以也就不能通过观察作用域来确定返回的引用是否总是有效。 为了修复这个错误我们将增加泛型生命周期参数来定义引用间的关系以便借用检查器可以进行分析。 生命周期注解并不改变任何引用的生命周期的长短。相反它们描述了多个引用生命周期相互的关系而不影响其生命周期。与当函数签名中指定了泛型类型参数后就可以接受任何类型一样当指定了泛型生命周期后函数也能接受任何生命周期的引用。 生命周期注解有着一个不太常见的语法生命周期参数名称必须以撇号开头其名称通常全是小写类似于泛型其名称非常短。大多数人使用 a 作为第一个生命周期注解。生命周期参数注解位于引用的 之后并有一个空格来将引用类型与生命周期注解分隔开。 简而言之通过生命周期注解我们告诉Rust函数有哪些参数与其返回值的生命周期进行关联。函数只能在它们生命周期重叠区域使用。 部分引用-slice 前面我们讲的引用都是引用整体对于一些序列型的数据类型例如字符串和array我们可以引用其部分数据这种引用类型称为slice。字符串slice使用下标区间从字符串获得引用值 fn main() {let s String::from(hello world);let hello s[0..5];let world s[6..11]; }字符串字面值的类型是 str它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面值是不可变的str 是一个不可变引用。 我们也会想要引用数组的一部分。我们可以这样做 let a [1, 2, 3, 4, 5]; let slice a[1..3]; assert_eq!(slice, [2, 3]); 这个 slice 的类型是 [i32]。它跟字符串 slice 的工作方式一样通过存储第一个集合元素的引用和一个集合总长度。你可以对其他所有集合使用这类 slice。 智能指针 智能指针smart pointers是一类数据结构他们的表现类似指针但是也拥有额外的元数据和功能。在 Rust 中普通引用和智能指针的一个区别是引用是一类只借用数据的指针相反在大部分情况下智能指针 拥有 他们指向的数据。 智能指针通常使用结构体实现。智能指针不同于结构体的地方在于其实现了 Deref 和 Drop trait。Deref trait 允许智能指针结构体实例表现的像引用一样这样就可以编写既用于引用、又用于智能指针的代码。Drop trait 允许我们自定义当智能指针离开作用域时运行的代码。 BoxT 前面我们提到了栈上的值不会被多个变量共享只会产生多个拷贝。但有时候我们希望将值在堆上开辟。这里使我们不得不这么做的一个例子是递归类型。BoxT使我们能够像指针变量一样访问值类型。它们多用于如下场景 当有一个在编译时未知大小的类型而又想要在需要确切大小的上下文中使用这个类型值的时候当有大量数据并希望在确保数据不被拷贝的情况下转移所有权的时候当希望拥有一个值并只关心它的类型是否实现了特定 trait 而不是其具体类型的时候 RCT 前面我们提到了Rust是单所有权的如果想使用多所有权就是要使用引用计数。Rust的RcT类型可以实现这个功能。RcT 只能用于单线程场景。可以通过RC::clone()来增加引用计数RcT 的引用计数叫strong_count。而WeakT的引用计数叫weak_count。通过不可变引用 RcT 允许在程序的多个部分之间只读地共享数据。 RefCellT 前面我们提到借用规则规定在有不可变引用时不可以改变数据。然而特定情况下令一个值在其方法内部能够修改自身而在其他代码中仍视为不可变是很有用的。值方法外部的代码就不能修改其值了。RefCellT 是一个获得内部可变性的方法。RefCellT 并没有完全绕开借用规则编译器中的借用检查器允许内部可变性并相应地在运行时检查借用规则。如果违反了这些规则会出现 panic 而不是编译错误。 当创建不可变和可变引用时我们分别使用 和 mut 语法。对于 RefCellT 来说则是 borrow 和 borrow_mut 方法这属于 RefCellT 安全 API 的一部分。borrow 方法返回 RefT 类型的智能指针borrow_mut 方法返回 RefMutT 类型的智能指针。这两个类型都实现了 Deref所以可以当作常规引用对待。 RefCellT 记录当前有多少个活动的 RefT 和 RefMutT 智能指针。每次调用 borrowRefCellT 将活动的不可变借用计数加一。当 RefT 值离开作用域时不可变借用计数减一。就像编译时借用规则一样RefCellT 在任何时候只允许有多个不可变借用或一个可变借用。 总结相较于RCT的多所有权RefCellT是单所有权的。它们都允许有多个引用但是RCT的引用都是不可变的而RefCellT可以返回可变引用。BoxT 允许在编译时执行不可变或可变借用检查RefCellT 允许在运行时执行不可变或可变借用检查。 WeakT 在使用引用计数的语言里都面临一个因循环引用导致引用计数不能减少到0而造成内存泄露的问题。可以使用WeakT来解决该问题。 参考 1.Rust 程序设计语言 简体中文版
http://www.hkea.cn/news/14451768/

相关文章:

  • 福永响应式网站建设中英文双语网站站点
  • 网站建设用户核心c .net网站开发视频教程
  • 韩国在中国做美食的视频网站建站公司上海
  • 郑州网站建设zzjisu四川省网站建设
  • 内蒙古自治区工程建设网站兴宁网站设计
  • 做电影网站需要的服务器配置php 同学录在线网站开发
  • 泰兴做网站的公司wordpress4.8优化
  • 合肥市建设局网站微信小程序与公众号的区别
  • wordpress回收站建设免费网站模板
  • 做网站用了别人公司的图片可以吗软件拉新推广平台
  • 林河西网站建设网页设计与制作教程的出版社
  • 网站多语言 设计西安seo服务外包
  • 做电商网站哪里好wordpress连接失效
  • 做汽车行业必须注册际零件网站seo百度点击软件
  • 网站开发 培训 周末班高稳定性的网站设计制作
  • 宁波网站备案幕布拍照济南手机网站制作
  • 宁波网站建设官门户手机网站开发
  • 有域名如何做网站营销型网站的付费推广渠道
  • 长沙网站托管哪家好提升seo排名
  • 响应式网站用什么做企业网站实名审核中心
  • 环保网站模板下载企业网站建设 哪个公司做得好
  • 苏州那家公司做网站比较好wordpress随机文章
  • 重庆沙坪坝做网站百度搜索风云榜电视剧
  • 建公司网站美团服务商平台
  • 网站建设信息模板html成品网页模板下载
  • 小游戏网站建设麻涌网站建设公司
  • 如何做网站的伪静态页面做flash网站的软件
  • 网站设计的创新点腾讯免费网站建设
  • 宣城市政建设集团有限公司网站怎么做网站管理
  • 做类似3d溜溜的网站怎么做返利网之类的网站