旅游网站制作建设,wordpress屏蔽f12,在线智能识图,搜索引擎广告投放文章目录 一、string二、所有权2.1 所有权与作用域2.2 对所有权的操作2.2.1 转移2.2.3 拷贝2.2.3 传递 2.3 引用2.3.1 借用2.3.2 可变引用 一、string
之前学习过 Rust 只有几种基础的数据类型#xff0c;但是没有常用的字符串也就是String#xff0c;今天来学习一下 String… 文章目录 一、string二、所有权2.1 所有权与作用域2.2 对所有权的操作2.2.1 转移2.2.3 拷贝2.2.3 传递 2.3 引用2.3.1 借用2.3.2 可变引用 一、string
之前学习过 Rust 只有几种基础的数据类型但是没有常用的字符串也就是String今天来学习一下 String Rust 中 String 是标准库的一部分也就是 std::String 但是这个 String 与其他语言中的 String 稍有不同比如
可以看到当我想要以一种为指定字符串类型的方式定义了一字符串变量时编译器自动显示出的类型是 srr 而非 String, 而我指定了 String 类型后仍然有错而从编译器给出的提示不难看出“hello” 这样定义得到的是一个 “str” 类型的值而非是个字符串那么我们先假定这是一种未知的类型后续再处理它先去想办法定义出我们的字符串打开官方文档 https://doc.rust-lang.org/std/string/struct.String.html
可以看到官方文档第一个示例告诉我们要像这样创建字符串:
但是官方没说为什么要这样定义幸好 Rust 的源码是可以点进去的 从 String::from 向里一步步执行
from 执行的操作只有一个就是调用 to_owned 函数但是需要注意这里传进来的参数类型仍然是str 然后 to_owned 下一步是调用 as_bytes().to_owned() ,最后这个 to_owned() 则是调用了 to_vec 那么至此也就明白了对于这一行代码: let hello String::from(Hello, );我们传入的 “Hello,” 这会被编译器认为是一个字符数组也就是一个字符串常量即无法对其造成改变的一个对象但是我们需要的是一个可变的字符串而非一组固定的字符因此编译器将这个字符数组扩展为了一个 vector , 也就变成了一个可变的字符数组也就是我最终想要的字符串
其实这和C差不多只不过Cstring底层应该直接是个指针而不是个vector
这样一来 “str” 也就理解了就是一个常量字符数组所以是不可变的。在官方文档搜一下果然也有并且还有个好听的名字字符串切片(string slice)具体参考 https://doc.rust-lang.org/std/primitive.str.html
官方文档中还介绍了两种类型的互转方法
剩下的使用就是这两种类型自带的一些接口了具体请参阅官方文档这里不再细述
二、所有权
2.1 所有权与作用域
很多小伙伴开始学习 Rust 是因为听说这是一种比C更安全的语言所以来了解一下那么它安全在哪里就安全在所有权机制不再需要开发者像C一样的去人工管理内存。
首先所有程序都必须管理其运行时使用计算机内存的方式。一些语言中具有垃圾回收机制在程序运行时有规律地寻找不再使用的内存比如Java另一些语言中程序员必须亲自分配和释放内存比如C/C。Rust 则选择了第三种方式通过所有权系统管理内存编译器在编译时会根据一系列的规则进行检查。如果违反了任何这些规则程序都不能编译。在运行时所有权系统的任何功能都不会减慢程序。所有权有以下规则
* Rust 中的每一个值都有一个 所有者owner。
* 值在任一时刻有且只有一个所有者。
* 当所有者变量离开作用域这个值将被丢弃。举个例子有以下一段代码
fn main() {let s1 hello;{ let s hello s; } let s2 hello;
}在上面的代码中 s 被一个括号圈住了那么在这个括号里hello s 的所有者就是 s而 s 的生命周期也只在括号范围内也就是 s1 出现时 s 未出现 s2 出现时 s 已经死去。
有过C 经验的小伙伴看到这肯定很熟悉这不就是 RAII 吗或者说 Rust 中的每个变量都是个智能指针。
2.2 对所有权的操作
2.2.1 转移
刚刚说到这种所有权机制与C的 RAII 很像变量也和智能指针很像那么是不是就和智能指针一样呢测试一下
图上可以看到先定义了 s1 然后定义 s2 然后将 s1 传递给 s2 此时再使用 s1 会报错提醒你s1 的值已经被转移出去了 这时 s1 就已经被清空了。因为 Rust 变量离开作用域时会回收所以如果这里不清空在程序结束时s1 s2都会被回收那么一块内存就会回收了两次因此 Rust 的机制中 操作是转移而非拷贝。
看到这里还是觉得是智能指针只不过是unique_ptrQAQ
2.2.3 拷贝 是转移而不是拷贝那么想要使用拷贝该怎么写呢比如字符串这样
调用 clone 函数就行了。
然后有一个很有意思的事情比如
i32 类型变量不需要使用 clone 之类的函数 居然就是拷贝而不是转移 官方给出的解释是 “像整型这样的在编译时已知大小的类型被整个存储在栈上所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 y 后使 x 无效。” 恕我直言这不就是Rust中所有用到堆的变量就用的是智能指针吗。。。。。当然也可能是我理解不够深反正我目前为止的感受就是这样。。。。
2.2.3 传递
之前提到过 “值在任一时刻有且只有一个所有者” 那么如果将值传递给函数会怎么样呢
很明显作为参数传递给函数之后就失去了所有权 但这样会带来一个问题这个值如果不只一个函数再用后续怎么办用函数返回值返回 但是如果参数不只有一个呢为每个函数的返回值都定一个结构体 这样太麻烦了万幸的是 Rust 提供了 引用。
2.3 引用
2.3.1 借用
官方说明中“引用reference像一个指针因为它是一个地址我们可以由此访问储存于该地址的属于其他变量的数据。 与指针不同引用确保指向某个特定类型的有效值。” 很好理解改一下刚才的代码
可以用了修改就是函数声明参数时加了一个传参时也加了一个
变量 str 有效的作用域与函数参数的作用域一样不过当 str 停止使用时并不丢弃引用指向的数据因为 str 并没有所有权。当函数使用引用而不是实际值作为参数无需返回值来交还所有权因为就不曾拥有所有权。
Rust 将创建一个引用的行为称为 借用borrowing。正如现实生活中如果一个人拥有某样东西你可以从他那里借来。当你使用完毕必须还回去并不拥有它因此借用的值无法修改。
2.3.2 可变引用
正如不可变变量与可变变量一样引用也可以变为可变引用加个 mut 关键试试
当然像这段代码所写的想要成为可变引用的前提是自身就是可变的。 另外由于 Rust 的三条基础规则之“值在任一时刻有且只有一个所有者”那么对于一个可变变量在同一个时刻也就不可以有多个引用换个角度理解比如用一个 s1 作为 s 的可变引用后那么 s 将不再可用也自然不能再对一个无法使用的变量创建引用如果这样使用编译器就会报错