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

唐山网站制作方案wordpress单页主题

唐山网站制作方案,wordpress单页主题,武冈企业建站,新华路街道网站建设1.什么是所有权? Rust 的核心功能#xff08;之一#xff09;是 所有权#xff08;ownership#xff09;。虽然该功能很容易解释#xff0c;但它对语言的其他部分有着深刻的影响。 所有程序都必须管理其运行时使用计算机内存的方式。一些语言中具有垃圾回收机制#x…1.什么是所有权? Rust 的核心功能之一是 所有权ownership。虽然该功能很容易解释但它对语言的其他部分有着深刻的影响。 所有程序都必须管理其运行时使用计算机内存的方式。一些语言中具有垃圾回收机制在程序运行时有规律地寻找不再使用的内存,例如:Java、Go在另一些语言中程序员必须亲自分配和释放内存,例如:C、C。Rust 则选择了第三种方式通过所有权系统管理内存编译器在编译时会根据一系列的规则进行检查。如果违反了任何这些规则程序都不能编译。在运行时所有权系统的任何功能都不会减慢程序。 因为所有权对很多程序员来说都是一个新概念需要一些时间来适应。随着你对 Rust 和所有权系统的规则越来越有经验你就越能自然地编写出安全和高效的代码, 需要学习者能够持之以恒。 当理解了所有权将会有一个坚实的基础来理解那些使 Rust 独特的功能。 2.栈和堆基础 在很多语言中并不需要经常考虑到栈与堆。不过在像 Rust 这样的系统编程语言中值是位于栈上还是堆上在更大程度上影响了语言的行为以及为何必须做出这样的抉择。 栈和堆都是代码在运行时可供使用的内存但是它们的结构不同。栈以放入值的顺序存储值并以相反顺序取出值。这也被称作 后进先出last in, first out。 增加数据叫做 进栈pushing onto the stack而移出数据叫做 出栈popping off the stack。栈中的所有数据都必须占用已知且固定的大小。在编译时大小未知或大小可能变化的数据要改为存储在堆上。 堆是缺乏组织的当向堆放入数据时你要请求一定大小的空间。内存分配器memory allocator在堆的某处找到一块足够大的空位把它标记为已使用并返回一个表示该位置地址的 指针pointer。这个过程称作 在堆上分配内存allocating on the heap有时简称为 “分配”allocating。因为指向放入堆中数据的指针是已知的并且大小是固定的你可以将该指针存储在栈上不过当需要实际数据时必须访问指针。 入栈比在堆上分配内存要快因为入栈时分配器无需为存储新数据去搜索内存空间其位置总是在栈顶。相比之下在堆上分配内存则需要更多的工作这是因为分配器必须首先找到一块足够存放数据的内存空间并接着做一些记录为下一次分配做准备。 访问堆上的数据比访问栈上的数据慢因为必须通过指针来访问。现代处理器在内存中跳转越少就越快缓存。出于同样原因处理器在处理的数据彼此较近的时候比如在栈上比较远的时候比如可能在堆上能更好的工作。当你的代码调用一个函数时传递给函数的值包括可能指向堆上数据的指针和函数的局部变量被压入栈中。当函数结束时这些值被移出栈。 跟踪哪部分代码正在使用堆上的哪些数据最大限度的减少堆上的重复数据的数量以及清理堆上不再使用的数据确保不会耗尽空间这些问题正是所有权系统要处理的。一旦理解了所有权就不需要经常考虑栈和堆了不过明白了所有权的主要目的就是为了管理堆数据能够帮助解释为什么所有权要以这种方式工作。 3.所有权规则 所有权规则核心主要有三条,务必牢记: 1.Rust 中的每一个值都有一个 所有者owner。 2.值在任一时刻有且只有一个所有者。 3.当所有者变量离开作用域这个值将被丢弃。 在所有权的第一个例子中我们看看一些变量的 作用域scope。作用域是一个项item在程序中有效的范围。假设有这样一个变量 let s hello; 变量 s 绑定到了一个字符串字面值这个字符串值是硬编码进程序代码中的。这个变量从声明的点开始直到当前 作用域 结束时都是有效的。可以看下面的标注: {                     // s 在这里无效它尚未声明let s hello;// 从此处起s 是有效的 ​// 使用 s } // 此作用域已结束s 不再有效 换句话说这里有两个重要的时间点 当 s 进入作用域 时它就是有效的。 这一直持续到它 离开作用域 为止。 目前为止变量是否有效与作用域的关系跟其他编程语言是类似的。现在在此基础上介绍 String 类型。 看下面的一段代码: let s String::from(hello); 这两个冒号 :: 是运算符允许将特定的 from 函数置于 String 类型的命名空间namespace下而不需要使用类似 string_from 这样的名字。 可以 修改此类字符串如下: let mut s String::from(hello); ​ s.push_str(, world!); // push_str() 在字符串后追加字面值 ​ println!({}, s); // 将打印 hello, world! 我们已经见过字符串字面值即被硬编码进程序里的字符串值, 它们是不可变的。那么这里有什么区别呢为什么 String 可变而字面值却不行呢区别在于两个类型对内存的处理上。 4.所有权内存和分配 对于字符串字面值我们在编译时就知道其内容所以文本被直接硬编码进最终的可执行文件中。这使得字符串字面值快速且高效。不过这些特性都只得益于字符串字面值的不可变性。不幸的是我们不能为了每一个在编译时大小未知的文本而将一块内存放入二进制文件中并且它的大小还可能随着程序运行而改变。 对于 String 类型为了支持一个可变可增长的文本片段需要在堆上分配一块在编译时未知大小的内存来存放内容。这意味着 必须在运行时向内存分配器memory allocator请求内存。 需要一个当我们处理完 String 时将内存返回给分配器的方法。 第一部分由我们完成当调用 String::from 时它的实现 (implementation) 请求其所需的内存。这在编程语言中是非常通用的。 然而第二部分实现起来就各有区别了。在有 垃圾回收garbage collectorGC的语言中GC 记录并清除不再使用的内存而我们并不需要关心它。在大部分没有 GC 的语言中识别出不再使用的内存并调用代码显式释放就是我们的责任了跟请求内存的时候一样。从历史的角度上说正确处理内存回收曾经是一个困难的编程问题。如果忘记回收了会浪费内存。如果过早回收了将会出现无效变量。如果重复回收这也是个 bug。我们需要精确的为一个 allocate 配对一个 free。 Rust 采取了一个不同的策略内存在拥有它的变量离开作用域后就被自动释放。下面是作用域例子的一个使用 String 而不是字符串字面值的版本 {let s String::from(hello); // 从此处起s 是有效的 ​// 使用 s}                                 // 此作用域已结束// s 不再有效 这是一个将 String 需要的内存返回给分配器的很自然的位置当 s 离开作用域的时候。当变量离开作用域Rust 为我们调用一个特殊的函数。这个函数叫做 drop在这里 String 的作者可以放置释放内存的代码。Rust 在结尾的 } 处自动调用 drop。 这个模式对编写 Rust 代码的方式有着深远的影响。现在它看起来很简单不过在更复杂的场景下代码的行为可能是不可预测的比如当有多个变量使用在堆上分配的内存时。下面来探索一些场景。 5.变量与数据交互方式之移动 在 Rust 中多个变量可以采取不同的方式与同一数据进行交互。看下面的例子: let x 5; let y x; 我们大致可以猜到这在干什么将 5 绑定到 x接着生成一个值 x 的拷贝并绑定到 y。现在有了两个变量x 和 y都等于 5。因为整数是有已知固定大小的简单值所以这两个 5 被放入了栈中。 现在看看这个 String 版本 let s1 String::from(hello); let s2 s1; 这看起来与上面的代码非常类似所以我们可能会假设它们的运行方式也是类似的也就是说第二行可能会生成一个 s1 的拷贝并绑定到 s2 上。不过事实上并不完全是这样。 下面先看一张图解: 从左边代表的s1内容可以看到, String是由三部分组成: 一个指向存放字符串内容内存的指针, 一个是长度和一个容量。这一组数据存储在栈上, 而右侧的数据, 也就是hello字符串内容则是存储在堆上。 这里我们要区分一下长度和容量。长度是表示String的内容当前使用了多少字节的内存; 而容量是String从分配器总共获取了多少字节的内存。长度和容量的区别非常重要, 但在这里的上下文中并不重要, 所以现在暂时忽略容量。 当我们将s1赋值给s2, String的数据被复制了, 这意味着我们从栈上拷贝了它的指针、长度和容量。但并没有复制指针指向的堆上的数据:hello, 为了更好的理解, 可以参考下面的图解: 从图中可以看出, 将s1赋给s2之后, s2有一份s1的拷贝,内容是: ptr、len和capacity, 设想一下, 如果此时Rust也拷贝了堆上的数据将会发生什么?那么内存看起来就像下面这样: 如果Rust真的这样做了, 在操作s2 s1的过程中,假如堆里的数据不是hello,而是一串大数据, 那么在运行时可能会对性能造成重大的影响。 之前我们提到过当变量离开作用域后Rust 自动调用 drop 函数并清理变量的堆内存。当执行语句:s2 s1时, 两个数据指针指向了同一个位置, 此时就有一个问题: 当s2和s1离开作用域, 它们都会尝试释放相同的内存, 这是一个典型的二次释放(double free)的错误, 也是之前提到过的内存安全性bug之一, 两次释放(相同)内存会导致内存污染, 它可能会导致潜在的安全漏洞。 为了确保内存安全在 let s2 s1; 之后Rust 认为 s1 不再有效因此 Rust 不需要在 s1 离开作用域后清理任何东西。看看在 s2 被创建之后尝试使用 s1 会发生什么, 代码如下: let s1 String::from(hello); let s2 s1; ​ println!({}, world!, s1); 这段代码执行后, 会得到一个错误, 因为Rust禁止使用无效的引用,如图: 如果在其他语言中听说过术语 浅拷贝shallow copy和 深拷贝deep copy那么拷贝指针、长度和容量而不拷贝数据可能听起来像浅拷贝。不过因为 Rust 同时使第一个变量无效了这个操作被称为 移动move而不是叫做浅拷贝。上面的例子可以解读为 s1 被 移动 到了 s2 中。那么具体发生了什么,可以参考下图: 当执行let s2 s1后, s1被移动到s2, 随后被释放, 这样就解决了二次释放问题, 只有s2是有效的, 当其离开作用域, s2会释放自己的内存,完美解决。 另外这里还隐含了一个设计选择Rust 永远也不会自动创建数据的 “深拷贝”。因此任何 自动 的复制可以被认为对运行时性能影响较小。 6.总结 在本章节中, 我们学习到Rust的以下知识: (1). 对所有权的规则原理和内存管理有了一个清晰的认识。 (2). 探讨研究了Rust的所有权内存分配机制。 (3). 研究了Rust变量和数据交互的底层原理, 弄清楚了 移动 机制。 在下一篇文章中,我们将学习所有权的以下知识点: (1).变量与数据交互的另一种方式: 克隆 (2).所有权与函数 (3).返回值与作用域
http://www.yutouwan.com/news/138408/

相关文章:

  • 营销型网站建设微博wordpress无法进入登录页面
  • 网站开发经理招聘极验验证+wordpress
  • 国外网站空间租用费用临沂做百度网站软件公司
  • 网站制作公司报价网站系统维护一个月正常吗
  • 沈阳市浑南区城乡建设局网站在线图片修改
  • php网站系统东莞网站关键词优化哪家好
  • 企业网站建设管理平台如何查注册商标是别人注册过的
  • vi设计网站大全wordpress按照证书
  • 专业做网站上海开设计公司要怎么规划
  • 菏泽网站建设便宜臻动传媒网站建设电商学堂
  • 苏州建设银行网站首页国外性价比高的vps
  • 西安高校定制网站建设公司推荐山西网站的公司
  • 买卖网站建设电商网站建设分析
  • 一个dede管理两个网站东莞松山湖风景区
  • 国外虚拟服务器网站广州行业门户网站建设
  • 网页设计做一个介绍自己的的网站wordpress 微信同步
  • 聊城网站案例网站名字大全
  • h5成品网站做网站需要套模板
  • 北京seo网站结构优化网站用的服务器多少钱
  • 怎样开通网站太原seo外包公司
  • 网站源码文件安装教程超级商城
  • sns社交网站wordpress inc文件夹
  • 网站群建设工作如何在手机上做自己的网站
  • 黄山家居网站建设怎么样网站建设前端和后端的区别
  • 上海好的网站设计公司有哪些男女做微电影网站
  • 贵阳网站建设制作方法建设和管理环保网站
  • word如何做网站链接重庆大渝网官网
  • 网站建设公司浩森宇特wordpress 京东导购
  • 邯郸商城网站建站重庆网络推广平台
  • 广西建设领域证书查询官方网站中国建设部网站能查叉车证