首页 > 其他分享 >番外-rust基础move_semantics-移动语义

番外-rust基础move_semantics-移动语义

时间:2025-01-17 11:54:08浏览次数:1  
标签:移动 番外 move let Rust println 所有权 s1 rust

Rust 中的 move semantics(移动语义) 是其所有权系统的核心特性之一。它决定了数据的所有权如何在程序中转移以及如何在程序执行过程中确保内存安全。

1. 基本概念:所有权(Ownership)

Rust 的所有权系统要求每个值都有一个所有者,并且该值在同一时间只能有一个所有者。这就引入了 所有权的转移(move)借用(borrow) 两个关键概念。

2. 移动语义(Move Semantics)

在 Rust 中,当你将一个变量赋值给另一个变量时,默认情况下是 移动(move) 数据的所有权,而不是复制数据。这意味着,原来的变量不再拥有该数据,且不能再访问它,直到它被重新赋值。

3. Move vs Clone

在默认情况下,Rust 会 移动 数据的所有权,而不是复制数据。如果你想要 复制 数据而不是移动,你需要显式调用 clone() 方法。clone() 会为数据分配新的内存并将数据复制过去。

示例:移动(Move)消费

fn main() {
    let s1 = String::from("Hello");
    let s2 = s1; // s1 的所有权被移动到 s2

    // println!("{}", s1); // 错误!s1 已经不再拥有数据
    println!("{}", s2); // 输出: Hello
}

在这个例子中,s1 的所有权被移动到 s2,因此 s1 在移动后不再有效。如果你尝试使用 s1,会导致编译错误。

示例:克隆(Clone)-不想被消费,保留原来的使用权

fn main() {
    let s1 = String::from("Hello");
    let s2 = s1.clone(); // 复制数据,而不是移动所有权

    println!("{}", s1); // 输出: Hello
    println!("{}", s2); // 输出: Hello
}

在这个例子中,clone() 方法被用来创建 s1 的一个深拷贝,因此 s1 仍然有效。

4. 函数中的移动

当你将一个变量作为函数的参数传递时,Rust 会根据该变量的类型决定是否移动所有权。

示例:在函数中移动所有权

fn take_ownership(s: String) {
    println!("{}", s);
}

fn main() {
    let s1 = String::from("Hello");
    take_ownership(s1); // 所有权被移动到函数参数 `s`

    // println!("{}", s1); // 错误!s1 不再有效
}

在上面的例子中,当 s1 被传递到 take_ownership 函数时,它的所有权被移动到函数中的参数 s。因此,在函数调用之后,s1 无法再访问 s1 中的数据。

5. 借用(Borrowing)

借用是 Rust 通过引用来实现的。在借用的情况下,数据的所有权不会发生转移,引用者只是对数据的“借用者”。

Rust 的借用有两种形式:

  • 不可变借用:允许多个引用同时访问数据,但无法修改数据。
  • 可变借用:允许只有一个引用可以修改数据。

示例:不可变借用

fn main() {
    let s = String::from("Hello");
    let s_ref = &s; // 不可变借用

    println!("{}", s_ref); // 输出: Hello
    // s_ref 可以继续使用,但无法修改 s
}

示例:可变借用

fn main() {
    let mut s = String::from("Hello");
    let s_ref = &mut s; // 可变借用

    s_ref.push_str(", World!");
    println!("{}", s_ref); // 输出: Hello, World!
}

在可变借用的情况下,只有一个引用能够修改数据。如果尝试同时拥有多个可变引用或混合可变和不可变引用,Rust 会在编译时进行检查并报错,确保数据的一致性和安全性。

6. 移动与复制的区别

在 Rust 中,实现 Copy trait 的类型会自动复制数据,而不是移动所有权。对于简单的类型如 i32f64char 和其他原始类型,Rust 会在传递这些类型的变量时进行 复制

示例:Copy 类型

fn main() {
    let x = 5;
    let y = x; // 对于 `Copy` 类型,x 会被复制,而不是移动

    println!("{}", x); // 输出: 5
    println!("{}", y); // 输出: 5
}

i32 实现了 Copy trait,因此 x 在赋值给 y 时会被复制,而不是移动。

7. 结构体与移动语义

Rust 中的结构体如果包含非 Copy 类型字段(如 StringVec),那么结构体的所有权也会被移动。

示例:结构体移动

struct Person {
    name: String,
}

fn take_ownership(person: Person) {
    println!("{}", person.name);
}

fn main() {
    let p = Person {
        name: String::from("Alice"),
    };

    take_ownership(p); // 所有权被移动到函数

    // println!("{}", p.name); // 错误!p 不再有效
}

在这个例子中,p 的所有权被移动到 take_ownership 函数中,因此在函数调用之后,p 无法再访问。

8. 总结:Rust 的移动语义

Rust 的移动语义通过所有权系统来确保内存安全和无数据竞争。数据的所有权在默认情况下会被移动,而不是复制,除非该类型实现了 Copy trait。借用则允许你引用数据而不转移所有权,从而使得你能够有效地管理资源的使用而不需要复制或移动数据。

  • 移动(Move):会将数据的所有权从一个变量转移到另一个变量,源变量不再有效。
  • 克隆(Clone):显式复制数据,分配新的内存空间,源变量和目标变量都有效。
  • 借用(Borrowing):通过引用传递数据,不涉及所有权的转移。

标签:移动,番外,move,let,Rust,println,所有权,s1,rust
From: https://www.cnblogs.com/learnForLife/p/18676672

相关文章

  • 番外-rust迭代器-iter()
    iter()是Rust中的一个方法,它可以用于可迭代的集合,返回一个不可变的迭代器。这个方法使得你可以遍历集合中的元素。通常,iter()适用于以下几种类型:1.数组(Array)数组是固定大小的集合,iter()可以用来遍历数组中的元素。示例:letarr=[1,2,3];foriteminarr.iter(){......
  • 4. rust基础Vec-可变数组
    Vec基本知识定义Vec是一个存储堆分配的数据类型,可以动态改变大小。你可以将元素推送到Vec中,或者从其中删除元素。动态大小不像数组([T;N])那样大小固定,Vec的大小在运行时是可变的。你可以向Vec添加元素,也可以删除元素,甚至将它的容量增加或减少。如何使用Vec1.......
  • rust学习十七.1、async和await
    本文对应相关书籍17.1章节。先言:async和多线程没有什么密切关系,当然也不是毫无关系!一、async在rust到底是什么async中文的意思是异步,在编程中指的是:执行一段代码,主线程可以在等待完成之前,先做其它事情。如果有写过前端代码,就明白这个东西。例如经典的jquery的ajax默认就是异步......
  • Rust程序Vec中存储的一般都是Box动态指针吗?
    Rust程序Vec中存储的一般都是Box动态指针吗?UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU在Rust中,Vec<T>不是专门存储Box<T>或其他动态指针,而是存储类型T的值。具体来说,Vec<T>会按照值的类型T来管理数据,它通常使用堆分配内存来存储数据(对于较大的数据或当数据需要动态增长时......
  • Rust如何在代码中查看一个变量的数据类型?
    Rust如何在代码中查看一个变量的数据类型?UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU在Rust中,你可以使用std::any::TypeId来查看一个变量的类型,但是这种方式通常用于调试或元编程,而不是日常开发的主要方法。Rust是强类型语言,通常在编译时就能检查类型,开发者无需显式查看类型。但......
  • 【ROS2】实操Movei2!路径规划
     本篇文章需要将前面几个关于moveit的内容手敲以便,熟悉基本流程再来实操! 一、规避障碍物1.1AddincludeforPlanningSceneInterface添加引用头文件:#include<moveit/planning_scene_interface/planning_scene_interface.h>1.2ChangetheTargetPose重新设定目标......
  • Autopy 是一款基于 Python 和 Rust 的强大 GUI 自动化库
    Autopy是一款基于Python和Rust的强大GUI自动化库,它为开发者提供了简便且高效的API来模拟鼠标和键盘的操作、在屏幕上查找颜色和位图以及显示警报。这些功能使得Autopy成为了一个跨平台的自动化工具,适用于MacOSX、Windows以及支持XTest扩展的X11系统。跨......
  • 手机端rustdesk如何进行配置
    安装rustdesk客户端以后,可以按照下图填写配置信息手机版也是可以快速导入导出,可以方便从其他设备或者客户端直接导入配置信息,然后在本软件进行导入或者导出......
  • rustdesk如何开启远程教程
    手机端在软件底部选择【共享屏幕】,在共享屏幕里面选择启动服务。主控和被控手机同时都配置好了ID服务器的信息以后,在软件底部选择【连接】然后输入远程ID,选择连接就行了。提示输入密码,可以查看一下被控客户端的密码,或者可以给被控客户端设置固定密码。......
  • TrustRAG:增强RAG系统鲁棒性与可信度的创新框架
    在人工智能飞速发展的今天,大语言模型(LLMs)凭借其强大的语言处理能力在诸多领域大放异彩。检索增强生成(RAG)系统(面向企业RAG(RetrievalAugmentedGeneration)系统的多维检索框架)的出现,通过整合外部知识源进一步提升了LLMs的性能,使其能针对用户查询提供更准确、更具上下文相关性的......