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

电商网站与企业网站区别校园兼职网站开发用例图

电商网站与企业网站区别,校园兼职网站开发用例图,wordpress 快速建站,小程序软件开发本篇文章包含的内容1 重新从堆和栈开始考虑2 所有权规则3 变量和数据#xff08;值#xff09;的交互方式3.1 移动 Move3.2 克隆 Clone3.3 复制 Copy4 函数与所有权4.1 参数传递时的所有权转移4.2 函数返回时的所有权转移5 引用和借用6 切片前面两篇仅仅介绍了一些Rust的语法… 本篇文章包含的内容1 重新从堆和栈开始考虑2 所有权规则3 变量和数据值的交互方式3.1 移动 Move3.2 克隆 Clone3.3 复制 Copy4 函数与所有权4.1 参数传递时的所有权转移4.2 函数返回时的所有权转移5 引用和借用6 切片前面两篇仅仅介绍了一些Rust的语法以及一些程序书写特点。如果是其他语言其实已经可以说完成了六成以上的学习可以开始着手项目以实践驱动学习了。但所有权和生命周期才是Rust的魅力所在真正的难点现在才刚刚开始噔噔咚。 1 重新从堆和栈开始考虑 所有权是Rust最独特的特性之一使得它与Java、C#等语言相比不需要GCGarbage Collector垃圾收集器就可以保证内存安全同时也不需要像C/C一样手动释放内存。为了理解所有权我们必须了解Rust的内存分配机制这是在之前学习的语言中基本不会注意的点。 无论哪种语言编写的程序都必须考虑他们运行时对计算机内存的操作方式。Rust并不相信程序员但是也摒弃了GC算法这种低效的方式取而代之的是引入所有权的概念使程序中的内存操作错误在编译时就基本解决并且这种做法不会造成任何的运行时开销。 在程序运行时堆Heap和栈Stack都是程序可用的内存它们的本质区别是内存组织的方式不同。栈内存先入后出永远有一个指针指向栈顶内存的存储是连续的所有存储在栈中的数据必须有已知的或者固定的大小而堆内存相对比较混乱程序使用的内存是碎片化的一般在运行时申请的动态内存都属于堆内存操作系统在申请Heap时需要申请一个足够大的空间并返回一个额外的指针变量记录变量的存储位置并且需要做好记录和管理方便下次分配这导致程序运行时的指针可能存在大范围的跳转。总之栈内存效率更高堆内存以牺牲效率为代价换取了更多的灵活性。 所有权解决了以下问题 跟踪代码的哪些部分正在使用Heap的哪些数据最小化Heap上的重复数据量及时清理Heap上未使用的数据以避免空间不足。 2 所有权规则 Rust中所有权有以下三条规则它很重要先记下来再慢慢理解 每个值都有一个变量这个变量就是这个值的所有者每个值同时只能有一个所有者当所有者超出作用域Scope时该值将被删除。 下面是一个关于作用域Scope的简单例子。作用域的概念在其他编程语言中也有这里需要理解的是s是变量“hello”就是这个变量的值一个字符串字面值。 // s 无效 fn main() {// s 无效let s hello; // s 可用// s 继续有效 } // s 的作用域从这里结束通过第一部分的解释这里就比较好理解变量s的存储方式了。它的值在编译时就已经全部确定并且不会随之变化如果需要变化则需要引入String类型所以这个变量和它的值在编译时就会被全部写入可执行文件中。 与之相比String类型在堆上分配这使得它可以存储在编译时未知数量的文本。下面的例子中s超出作用域时会自动调用一个特殊的名为drop的函数来释放内存。所以String类型是一个实现了Drop traittrait接口的类型。 fn main() {let mut s String::from(Hello);s.push_str(, world!);println!({}, s); } // s 会自动调用一个drop函数看到这里你可能依然一头雾水这家伙在说什么呢.jpg这些概念和C/C以及其他语言难道做不到吗超出作用域释放内存难道不是理所当然的吗既然如此我还为什么要学RustRust究竟好在哪所谓的内存安全就这   别急这个Drop方法看似人畜无害但是它会导致一个非常严重的bug。 3 变量和数据值的交互方式 3.1 移动 Move 首先看下面这个例子创建了两个简单的整数变量由于它们的大小是确定的所以两个变量都将被压入栈中值发生了复制。像整数这样完全存放在栈上的数据实现了Copy trait。 let x 5; let y x; // value copied here但是下面这个例子不同s1在内存中的索引信息存储在栈中s1所对应的内容需要被存放在堆中出于值的长度可变的需要。栈中包含一个指向字符串存储位置的指针一个字符串实际长度一个从操作系统中获得的内存的总字节数。 let s1 String::from(hello);如果接下来接着执行这一语句那么栈中s1的信息会被复制一份但是堆中字符串的值不会复制有点像浅拷贝s1的所有权将会直接被递交给s2同时s1会直接失效这时我们说值的所有权发生了移动Move。这样做的目的是避免两个字符串离开作用域时调用两次drop函数从而导致严重的Double Free错误。 let s2 s1; // value moved here println!({}, s1); // 编译直接报错3.2 克隆 Clone 对于上面的s1和s2的例子如果想同时拷贝栈和堆中的信息可以使用clone()方法。这样的操作明显是比较浪费资源的。 fn main() {let s1 String::from(hello);let s2 s1.clone();println!({} {}, s1, s2); }3.3 复制 Copy 总之如果一个变量存在Copy trait那么旧变量在“移动”后依然可用如果一个类型或者该类型的一部分实现了Drop triait例如定义的元组的一部分是String的情况那么Rust就不允许它再实现Copy trait了编译时就会进行检查在移动后旧变量就不再可用除非使用了clone()方法。 4 函数与所有权 Rust中的变量总是遵循下面的规则 把一个变量赋值给其他变量就会发生移动除非变量存在Copy trait当变量超出其作用域后存储在Heap上的数据就会被销毁Drop trait除非它的所有权已经被转移。 4.1 参数传递时的所有权转移 在Rust中如果函数参数的类型是一个实现了Drop trait的类型例如String类型把值传递给函数中往往伴随着所有权的转移也就是说旧变量对值的所有权会发生丢失这里发生的事情和把变量赋值给另一个变量是类似的。看下面这个例子 fn main() {let s1 String::from(hello);take_ownership(s1);// println!({}, s1); // 编译报错let x 1;makes_copy(x);println!(the x is {}, x); }fn take_ownership(some_string: String) {println!({}, some_string); }fn makes_copy(some_integer: i32) {println!({}, some_integer); } 对于String这种类型的变量直接将其作为函数参数时传入参数时helloString的所有权会从s1转换到函数内部的some_string程序运行到take_ownership函数之外时会自动调用Drop trait字符串的值的内存会被释放。但是对于实现了Copy trait的类型例如i32参数传递时会发生copy而不是move这样在函数调用后x变量依然是可用的。 4.2 函数返回时的所有权转移 这个比较好理解看下面一个例子 fn main() {let s1 gives_ownership();let s2 String::from(hello);let s3 takes_and_gives_back(s2); }fn gives_ownership() - String {let s String::from(hello);s }fn takes_and_gives_back(a_string: String) - String {a_string }对于gives_ownership函数在函数内部创建了一个新的String函数返回时不会将其销毁而是把它的所有权交给主函数的s1而takes_and_gives_back函数获取到s2到的所有权s2之后会失效返回时将String的所有权交还给主函数的s3。 5 引用和借用 但有些时候我们只想获得变量的值而不想它的所有权发生转移甚至丢失这时候就可以使用引用Reference。 fn main() {let s1 String::from(hello);let lenth calculate_length(s1);println!(The length of {} is {}., s1, lenth); }fn calculate_length(s: String) - usize {s.len() }在上面的例子中calculate_length函数使用了String的引用作为参数函数计算返回字符串长度后s1仍然是可用的。引用相当于一个指针它可以获取到变量对应的值但是不拥有它所以当其离开作用域时也无法销毁它。像这样把引用作为函数参数这个行为称为借用Borrow。 在Rust中引用和变量类似也分为可变的引用和不可变的引用创建的引用默认同样是不可变的。下面是一个使用可变引用的例子。 fn main() {let mut s1 String::from(hello);let lenth calculate_length(mut s1);println!(The length of {} is {}., s1, lenth); }fn calculate_length(s: mut String) - usize {s.push_str(, world!);s.len() }需要注意引用的特殊限制在特定的作用域内一个变量只能同时拥有一个可变的引用并且不能同时存在可变的引用和不可变的引用。一个变量可以拥有多个不可变的引用。Rust从编译层面解决了数据竞争的问题。 let mut s String::from(hello);let s1 mut s; let s2 mut s; // 非法let mut s String::from(hello); {let s1 mut s; } let s2 mut s; // 合法这样的做法还带来了另一个好处即永远不会存在“悬空引用”Dangling Reference一个引用或者指针指向一块内存但是这一块内存可能已经被释放或者被其他人使用了或者“野指针”。 总之引用一定满足下面的规则 引用一定有效引用一定满足下列条件之一不可能同时满足 存在一个可变引用存在任意数量的不可变引用。 6 切片 切片Slice是指一段数据的引用。这里的一段数据可以是String类型也可以是数组。字符串切片的写法如下所示类型名在程序中是str。 let s String::from(hello world);let hello s[0..5]; // 左闭右开此时相当于 s[..5] let world s[6..11] // 此时相当于 s[6..]let whole s[..] // 整个字符串的切片需要注意字符串切片的索引必须发生在有效的UTF-8字符边界内就是不能把字符切“坏”了否则程序就会报错退出。 为什么要使用切片看下面这个例子获取字符串中的各个单词如果字符串中没有空格则返回整个字符串。 fn main() {let s String::from(hello);let word_index first_word(s);println!({}, word_index); }fn first_word(s: String) - usize {let bytes s.as_bytes(); // 将String转换为字符数组for (i, item) in bytes.iter().enumerate() {if item b {return i;}}s.len() }上面这个程序虽然能完成一部分功能获取第一个空格的位置但是这个程序存在一个重要的结构性缺陷变量word_index和Strings之间没有任何联系即使s被释放或者被修改word_index也无法感知。 使用字符串切片重写上面的例子 fn main() {let s String::from(hello world);let word first_word(s); // 把s作为不可变的引用发生借用之后s都不可变// s.clear(); // s不可变println!({}, word); }fn first_word(s: String) - str {let bytes s.as_bytes(); // 将String转换为字符数组for (i, item) in bytes.iter().enumerate() {if item b {return s[..i];}}s[..] } 字符串子面值也是切片。利用这一特点我们可以将函数的参数类型改为字符串切片str使得函数可以直接接收字符串子面值作为参数这样函数就可以同时接收String和字符串切片两种类型的变量作为参数了。 fn main() {let word first_word(hello world); println!({}, word); }fn first_word(s: str) - str {let bytes s.as_bytes(); // 将String转换为字符数组for (i, item) in bytes.iter().enumerate() {if item b {return s[..i];}}s[..] }其他数组类型也存在切片例如使用下面的方法创建一个i32类型的切片程序中用[i32]表示该类型。 let a: [i32; 5] [1, 2, 3, 4, 5]; let slice a[1..3]; // slice类型是[i32]原创笔记码字不易欢迎点赞收藏~ 如有谬误敬请在评论区不吝告知感激不尽博主将持续更新有关嵌入式开发、FPGA方面的学习笔记。
http://www.zqtcl.cn/news/545087/

相关文章:

  • 网站换服务器php大流量网站开发规范
  • 网站备案主体域名平面设计线下培训班多少钱
  • 优秀网站专题wordpress 外部调用插件
  • 域名服务网站建设科技公司做棋子网站怎么提高浏览量
  • 用易语言做攻击网站软件下载彩页设计多少钱
  • 个人网站可以做淘宝推广手机版怎么用百度快照
  • 制作网站的公司叫什么外包软件
  • 廊坊企业建站模板邱县手机网站建设
  • 辽宁响应式网站费用建设银行官网app
  • 河北黄骅市网站建设网站外链的优化方法
  • 青岛城阳网站制作网站建设详细步骤
  • 先做网站再付款 怎么回答设计方案步骤
  • 汕头建站模板济南网站建设富库网络
  • 创业网站建设方案项目书手机app设计软件
  • 建设端午节网站的目的主题wordpress语法高亮插件
  • 做网站开发使用百分比的好处深圳建设网站公司简介
  • 行距网站上海专业网站建设机构
  • 闵行手机网站建设鲅鱼圈规划建设局网站
  • 合肥市城乡和建设网站网页设计与网站建设区别
  • 青岛网站建设企业建站北京网站模仿
  • 广州建设网站的公司简介湛江建设厅网站
  • 做网站不赚钱了网站关键词排行查询
  • 印度人通过什么网站做国际贸易三门峡做网站
  • 网站排名快速提升工具招远建网站首选公司
  • 手机网站格式商城网游开发公司
  • 手机怎样创建网站长春网站建设哪家专业
  • 做pop网站定制开发教程
  • 成都响应式网站建报告问题
  • 做设计找素材的+网站有哪些建立平台什么意思
  • 网站设置在哪里找宁德网站建设制作