当前位置:首页 > CN2资讯 > 正文内容

rustdesk api 服务器 rust服务器main

3天前CN2资讯

// 本页是对RUST第四章的学习汇总记录。


书址



4.1. 什么是所有权

1. 所有权是RUST语言的核心功能(之一)他是一种管理内存的方式


2. **所有权规则

  • Rust 中的每一个值都有一个 所有者(owner)。
  • 值在任一时刻有且只有一个所有者。
  • 当所有者(变量)离开作用域,这个值将被丢弃。

  • 3. **变量作用域

    fn main() { { // s 在这里无效, 它尚未声明 let s = "hello"; // 从此处起,s 是有效的(进入作用域) // 使用 s } // 此作用域已结束,s 不再有效(离开作用域) }
    • 当 s 进入作用域 时,它就是有效的。
    • 这一直持续到它 离开作用域 为止。

    4. String类型(字符串)

  • 这个类型管理被分配到堆上的数据,所以能够存储在编译时未知大小的文本。
  • (存储位置大小的文本)这意味着,需要开出未知大小的内存。这需要两个步骤:
    - 必须在运行时向内存分配器(memory allocator)请求内存。
    - 需要一个当我们处理完 String 时将内存返回给分配器的方法。
  • RUST内存在拥有它的变量离开作用域后就被自动释放。

  • 5. 变量与数据交互的方式(一):移动

    fn main() { let s1 = String::from("hello"); let s2 = s1; //如果这个时候再次尝试使用s1 println!("{},world",s1); //此时程序将会报错,因为Rust禁止无效的引用 }
    • 在 let s2=s1 之后,s1就不再有效。(Rust 不需要在 s1 离开作用域后清理任何东西。)
    • 有一个特例:Copy trait(如果一个类型实现了 Copy trait,那么一个旧的变量在将其赋值给其他变量后仍然可用)可以不使用clone
    fn main() { let x = 5; let y = x; println!("x = {}, y = {}", x, y);//这是合法的 }
    • 任何不需要分配内存或某种形式资源的类型都可以实现 Copy 。如下是一些 Copy 的类型:
  • 所有整数类型,比如 u32。
  • 布尔类型,bool,它的值是 true 和 false。
  • 所有浮点数类型,比如 f64。
  • 字符类型,char。
  • 元组,当且仅当其包含的类型也都实现 Copy 的时候。比如,(i32, i32) 实现了 Copy,但 (i32, String) 就没有

  • 6. 变量与数据交互的方式(二):克隆(clone)

    fn main() { let s1 = String::from("hello"); let s2 = s1.clone(); println!("s1 = {}, s2 = {}", s1, s2); }
    • 当出现 clone 调用时,你知道一些特定的代码被执行而且这些代码可能相当消耗资源。你很容易察觉到一些不寻常的事情正在发生。

    7. 所有权与函数

    fn main() { let s = String::from("hello"); // s 进入作用域 takes_ownership(s); // s 的值移动到函数里 ... // ... 所以到这里不再有效 let x = 5; // x 进入作用域 makes_copy(x); // x 应该移动函数里, // 但 i32 是 Copy 的, // 所以在后面可继续使用 x } // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走, // 没有特殊之处 fn takes_ownership(some_string: String) { // some_string 进入作用域 println!("{}", some_string); } // 这里,some_string 移出作用域并调用 `drop` 方法。 // 占用的内存被释放 fn makes_copy(some_integer: i32) { // some_integer 进入作用域 println!("{}", some_integer); } // 这里,some_integer 移出作用域。没有特殊之处
    • 变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。
    • 转移返回值的所有权:
    fn main() { let s1 = gives_ownership(); // gives_ownership 将返回值 // 转移给 s1 let s2 = String::from("hello"); // s2 进入作用域 let s3 = takes_and_gives_back(s2); // s2 被移动到 // takes_and_gives_back 中, // 它也将返回值移给 s3 } // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走, // 所以什么也不会发生。s1 离开作用域并被丢弃 fn gives_ownership() -> String { // gives_ownership 会将 // 返回值移动给 // 调用它的函数 let some_string = String::from("yours"); // some_string 进入作用域. some_string // 返回 some_string // 并移出给调用的函数 // } // takes_and_gives_back 将传入字符串并返回该值 fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域 // a_string // 返回 a_string 并移出给调用的函数 }

    补充:我们可以使用元组来返回多个值

    //元组 fn main() { let s1 = String::from("hello"); let (s2, len) = calculate_length(s1); println!("The length of '{}' is {}.", s2, len); } fn calculate_length(s: String) -> (String, usize) { let length = s.len(); // len() 返回字符串的长度 (s, length) }

    4.2. 引用与借用

    引用(reference)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。(与指针不同,引用确保指向某个特定类型的有效值。)

    规则:

  • 在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
  • 引用必须总是有效的。
  • //引用 fn main() { let s1 = String::from("hello"); let len = calculate_length(&s1);//&符号即引用(还有解引用‘ * ’) println!("The length of '{}' is {}.", s1, len); } fn calculate_length(s: &String) -> usize { s.len() }// 这里,s 离开了作用域。但因为它并不拥有引用值的所有权, // 所以什么也不会发生
    • 相比较元组:变量声明和函数返回值中的所有元组代码都消失了。
    • &s1 语法让我们创建一个 指向 值 s1 的引用,但是并不拥有它。因为并不拥有这个值,所以当引用停止使用时,它所指向的值也不会被丢弃。
    • 我们将创建一个引用的行为称为 借用(borrowing)。
    • 默认不允许修改引用的值

    可变引用

    fn main() { let mut s = String::from("hello"); change(&mut s); } fn change(some_string: &mut String) { some_string.push_str(", world"); }
  • 把s改为mut。
  • 创建可变引用&mut s并且更新函数签名以接受一个可变引用some_strinig:&mut String
    • 如果你有一个对该变量的可变引用,你就不能再创建对该变量的引用。尝试对一个变量创建两个可变引用的代码会失败(报错)一个可变引用必须持续到在一个println!(或者别的什么)中使用它。(一个引用的作用域从声明的地方开始一直持续到最后一次使用为止。)
    • 这样子限制的好处是避免数据竞争(这会导致未定义行为,难以在运行时追踪,并且难以诊断和修复):
    • 两个或更多指针同时访问同一数据
    • 至少有一个指针被用来写入数据
    • 没有同步数据访问的机制
    • 不可以在拥有不可变引用的时候拥有可变引用(不能同时使用可变和不可变引用)
    fn main() { let mut s = String::from("hello"); let r1 = &s; // 没问题 let r2 = &s; // 没问题 let r3 = &mut s; // '大问题' println!("{}, {}, and {}", r1, r2, r3); }

    悬垂引用

    悬垂指针是其指向的内存可能已经被分配给其它持有者在(Rust 中,编译器确保引用永远也不会变成悬垂状态:当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域。)

    fn main() { let reference_to_nothing = dangle(); } fn dangle() -> &String { // dangle 返回一个字符串的引用 let s = String::from("hello"); // s 是一个新字符串 &s // 返回字符串 s 的引用 } // 这里 s 离开作用域并被丢弃。其内存被释放。 // 危险!
    • 因为 s 是在 dangle 函数内创建的,当 dangle 的代码执行完毕后,s 将被释放。不过我们尝试返回它的引用。这意味着这个引用会指向一个无效的 String( s 已经被释放而无效化),这可不对!Rust 不会允许我们这么做。

    Slice类型

    slice 允许你引用集合中一段连续的元素序列,而不用引用整个集合。slice 是一类引用,所以它没有所有权

    • 编写一个函数,该函数接收一个用空格分隔单词的字符串,并返回在该字符串中找到的第一个单词。如果函数在该字符串中并未找到空格,则整个字符串就是一个单词,所以应该返回整个字符串。
    • 对于 Rust 的 .. range 语法,如果想要从索引 0 开始,可以不写两个点号之前的值。换句话说,如下两个语句是相同的:
    #![allow(unused)] fn main() { let s = String::from("hello"); let slice = &s[0..2]; let slice = &s[..2]; }
    • 如果 Slice 包含 String 的最后一个字节,也可以舍弃尾部的数字。这意味着如下也是相同的:
    #![allow(unused)] fn main() { let s = String::from("hello"); let len = s.len(); let slice = &s[3..len]; let slice = &s[3..]; }
    • 也可以同时舍弃这两个值来直接获取整个字符串的Slice,所以如下亦是相同的
    #![allow(unused)] fn main() { let s = String::from("hello"); let len = s.len(); let slice = &s[0..len]; let slice = &s[..]; }
    • 字符串字面值就是Slice
    • 字符串Slice作为参数:如果有一个字符串 slice,可以直接传递它。如果有一个 String,则可以传递整个 String 的 slice 或对 String 的引用。
    • 其他类型的Slice:就跟我们想要获取字符串的一部分那样,引用数组的一部分的时候,我们可以这样做:
    #![allow(unused)] fn main() { let a = [1, 2, 3, 4, 5]; let slice = &a[1..3]; assert_eq!(slice, &[2, 3]); }

    总结:

    • 所有权、借用和 slice 这些概念让 Rust 程序在编译时确保内存安全。Rust 语言提供了跟其他系统编程语言相同的方式来控制你使用的内存,但拥有数据所有者在离开作用域后自动清除其数据的功能意味着你无须额外编写和调试相关的控制代码。



      你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/20958.html

      分享给朋友:

      “rustdesk api 服务器 rust服务器main” 的相关文章

      永久循环优惠:如何通过长期折扣提升客户忠诚度与购买频率

      定义与特点 永久循环优惠是一种长期有效的营销策略,旨在通过持续的优惠措施吸引和保留客户。这种优惠方式的核心在于“永久”和“循环”,意味着优惠不会在短期内结束,而是会持续存在,甚至可能随着时间推移不断更新或调整。它的特点在于为消费者提供长期的实惠,同时帮助商家建立稳定的客户关系。 从消费者的角度来看,...

      ColoCrossing怎么样?高性价比与稳定性的最佳选择分析

      ColoCrossing是一家自2003年起在网络主机市场崭露头角的公司,位于美国纽约州的布法罗市。这家公司以其稳定的性能和合理的价格而闻名,在美国的多个大城市设有数据中心,实现了从东海岸到西海岸的覆盖。这一遍布美国的基础设施,能够为各类业务提供灵活且可靠的网络服务。作为一个用户,我总能感受到Col...

      SpartanHost VPS主机评测:高性能与安全性的理想选择

      在我开始探索VPS主机市场时,SpartanHost引起了我的注意。这个公司成立于2013年,自那时起便在行业中扎根,专注于提供高性能的VPS解决方案。他们使用的是基于KVM架构的主机产品,充分满足用户的需求。从他们的运营历史来看,尽管时间不算很久,但SpartanHost凭借其稳定的服务和灵活的选...

      PVE环境下是否需要设置路由器?轻松拷贝文件的最佳实践

      PVE概述 Proxmox Virtual Environment(PVE)是一个开源的虚拟化管理平台,集成了KVM和LXC技术。简单来说,它允许用户在一台物理服务器上创建和管理多个虚拟机和容器。使用PVE让你轻松地部署、监控和管理自己的虚拟化环境,不论是用于开发、测试,还是生产环境。PVE提供了一...

      DigitalOcean与Vultr的全面比较与选择建议

      DigitalOcean与Vultr概述 1.1 DigitalOcean简介 DigitalOcean成立于2012年,总部位于美国纽约,这家公司一开始就定位于为开发者提供高效的云计算服务。最初的目标是简化云计算,让更多人能够轻松使用这一新兴技术。随着时间的推移,DigitalOcean不断扩展其...

      搬瓦工:性能卓越的VPS服务平台,为您的项目提供最佳选择

      搬瓦工概述 在网上冲浪的时候,大家可能都听说过“搬瓦工”,但对于它的真正含义了解的并不多。搬瓦工(BandwagonHost)是一家以提供虚拟私人服务器(VPS)而闻名的公司,采用KVM架构,深受用户青睐。我在使用搬瓦工的过程中发现,选择这个平台的用户不仅因为它的价格相对较低,还因为它提供的服务非常...