草庐IT

Rust所有权和借用规则示例

千里之行,始于足下 2023-03-28 原文

众所周知,所有权是Rust区别于其他语言的一大特色,只要代码满足了所有权规则,我们就不用担心内存的泄露的问题。
让代码在编译阶段就解决内存的问题,而不是在运行崩溃后再调试。

Rust中,所有权和借用的规则其实并不复杂,所有权有3条规则,借用只有2条规则。

所有权的规则

1. Rust中的每一个值都有一个对应的变量作为它的所有者

这个规则很好理解,比如下面的2个值 5hello分别属于变量 xy

fn main() {
    let x = 5;
    let y = String::from("hello");

    println!("x = {}, and y = {}", x, y);
}

2. 在同一时间内,值有且仅有一个所有者

比如下面的示例,当 x的值给了 y之后,x就不能再用了,值hello只能有一个所有者。

fn main() {
    let x = String::from("hello");
    let y = x;

    println!("x = {}, y = {}", x, y); // 这里会报错
}

3. 当所有者离开自己的作用域时,它持有的值就会被释放掉

fn main() {
    let x = String::from("hello");
    {
        let y = String::from("world");
        println!("{} {}", x, y);
    }
    println!("{} {}", x, y); // 这里会报错,获取不到 y,y已经释放了。
}

借用(引用)的规则

Rust中,引用和借用是一个意思,用借用能更准确的表达变量传递的含义。

1. 在任何一段给定的时间里,你要么只能拥有一个可变引用,要么只能拥有任意数量的不可变引用

yz 都拥有x的不可变借用。

fn main() {
    let x = 5;

    let y = &x;
    let z = &x;

    println!("y = {}, z = {}", y, z);
}

如果 y拥有可变借用,而 z拥有不可变借用,是不行的。

fn main() {
    let mut x = 5;

    let y = &mut x;
    let z = &x;   // 这里会报错,因为同一段时间内,既有x的不可变借用,又有可变借用

    println!("y = {}, z = {}", y, z);
}

2. 借用总是有效的

只要借用能编译,就说明借用是有效的,编译器会帮助我们确保借用都是有效的。

fn main() {
    let x = vec![1, 2, 3];
    lost(x);

    let y = &x;    // 这里编译会报错,因为 x 已经转移到 lost 函数中,在 main 中失效了
    println!("y = {:?}", y);
}

fn lost(x: Vec<i32>) {
    println!("lost: {:?}", x);
}

下面这样借用就不会报错,因为x只是借用给 no_lost函数。

fn main() {
    let x = vec![1, 2, 3];
    not_lost(&x);

    let y = &x;
    println!("y = {:?}", y);
}

fn not_lost(x: &Vec<i32>) {
    println!("lost: {:?}", x);
}

总结

所有权和借用是Rust确保内存安全使用的重要手段,上面的示例用最简单的方式展示了这些规则。

实际项目中,刚开始其实很难保证所有权和借用的规则,会经常遇到编译不了的情况。
但是,一旦养成了习惯,写代码时,脑中自然浮现变量在内存中的情况,自然就写出了内存安全的代码。

有关Rust所有权和借用规则示例的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  3. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  4. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  5. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  6. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  7. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  8. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  9. ruby - 如何捕获 ruby​​ 中的所有异常? - 2

    我们如何捕获或/和处理ruby​​中所有未处理的异常?例如,这样做的动机可能是将某种异常记录到不同的文件或发送电子邮件给系统管理。在Java中我们会做Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandlerex);在Node.js中process.on('uncaughtException',function(error){/*code*/});在PHP中register_shutdown_function('errorHandler');functionerrorHandler(){$error=error_

  10. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

随机推荐