• rust结构体


    一、定义结构体类型

    语法

    struct Name_of_structure {
         field1: data_type,
         field2: data_type,
         field3: data_type,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:
    不同于C++,Rust的struct语句仅用来定义类型,不能定义实例。
    结尾不需要;。
    每个字段定义之后用 , 分隔。最后一个逗号可有可无。

    例子

    struct Site {
         domain: String,
         name: String,
         nation: String,
         found: u32,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    二、定义结构体实例

    1.语法

    let instance_name = Name_of_structure {
         field1: value1,
         field2: value2,
         field3: value3,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Rust受JavaScript影响,使用JSON对象的key: value语法定义结构体的实例

    例子

    let runoob = Site {
        domain: String::from("www.runoob.com"),
        name: String::from("RUNOOB"),
        nation: String::from("China"),
        found: 2013,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.如果字段名称和变量名称一样,可以简化书写:
    例子

    let domain = String::from("www.runoob.com");
    let name = String::from("RUNOOB");
    let runoob = Site {
        domain,  // 等同于domain : domain,
        name,    // 等同于name : name,
        nation: String::from("China"),
        found: 2013,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.复制现成的实例,只修改部分字段,可以使用如下语法

    let site = Site {
        domain: String::from("www.xx.com"),
        name: String::from("xx"),
        ..runoob,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这种语法要求至少重新设定一个字段的值

    三、元组结构体

    (一)
    元组结构体的形式是元组,与元组的区别是它有名字和固定的类型格式。
    它的意义是为了处理那些需要定义类型又不想太复杂的简单数据:

    struct Color(u8, u8, u8);
    struct Point(f64, f64);
    let black = Color(0, 0, 0);
    let origin = Point(0.0, 0.0);
    
    • 1
    • 2
    • 3
    • 4

    元组结构体的使用方式和元组一样,通过 . 和下标来访问
    例子

    fn main() {
        struct Color(u8, u8, u8);
        struct Point(f64, f64);
        let black = Color(0, 0, 0);
        let origin = Point(0.0, 0.0);
        println!("black = ({}, {}, {})", black.0, black.1, black.2);
        println!("origin = ({}, {})", origin.0, origin.1);
    }
    运行结果:
    black = (0, 0, 0)
    origin = (0, 0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (二)newtype模式
    newtype模式是使用元组结构体创建一个新类型,这个元组结构体只有一个字段,相当于对这个字段类型的封装。

    newtype模式的用处
    1.newtype模式可以用于确保某值不被混淆

    例子
    Years和Days结构体都封装了i64值。

    struct Years(i64);
    struct Days(i64);
    impl Years {
         pub fn to_days(&self) -> Days {
             Days(self.0 * 365)
         }
    }
    impl Days {
         pub fn to_years(&self) -> Years {
             Years(self.0 / 365)
         }
    }
    fn old_enough(age: &Years) -> bool {
         age.0 >= 18
    }
    fn main() {
         let age = Years(5);
         let age_days = age.to_days();
         println!("Old enough {}", old_enough(&age));
         println!("Old enough {}", old_enough(&age_days.to_years()));
         // println!("Old enough {}", old_enough(&age_days));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    取消最后一行的注释,就会报错。传给old_enough的参数类型必须是Years类型的。

    2.为外部类型实现外部trait
    参考Rust特性

    四、单元结构体

    结构体可以没有任何成员,称为单元结构体。

    struct MyStruct;
    
    • 1

    五、使用结构体

    (一)输出结构体
    以Debug方式打印结构体,需要实现Debug特性。
    实例

    #[derive(Debug)]
    struct Rectangle {
        width: u32,
        height: u32,
    }
    fn main() {
        let rect1 = Rectangle { width: 30, height: 50 };
        println!("rect1 is {:?}", rect1);
    }
    输出一整个结构体:
    rect1 is Rectangle { width: 30, height: 50 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (二)访问结构体实例的元素
    1.只读访问
    使用元素访问符,也就是点号 ( . )
    语法格式如下

    struct_name_instance.field_name
    
    • 1

    范例

    struct Employee {
         name: String,
         company: String,
         age: u32
    }
    fn main() {
         let emp1 = Employee {
              company:String::from("TutorialsPoint"),
              name:String::from("Mohtashim"),
              age:50
         };
         println!("Name is :{} company is {} age is {}", emp1.name, emp1.company, emp1.age);
    }
    编译运行结果如下
    Name is :Mohtashim company is TutorialsPoint age is 50
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.修改结构体实例的字段
    添加 mut 关键字,让它变成可修改的。
    范例

    struct Employee {
         name:String,
         company:String,
         age:u32
    }
    fn main() {
         let mut emp1 = Employee {
              company:String::from("TutorialsPoint"),
               name:String::from("Mohtashim"),
              age:50
         };
         emp1.age = 40;
         println!("Name is :{} company is {} age is {}", emp1.name, emp1.company, emp1.age);
    }
    编译运行结果如下
    Name is :Mohtashim company is TutorialsPoint age is 40
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    (三)结构体作为函数的参数
    例子

    //定义一个结构体
    struct Employee {
         name:String,
         company:String,
         age:u32
    }
    fn main() {
         //初始化结构体
         let emp1 = Employee {
              company:String::from("TutorialsPoint"),
              name:String::from("Mohtashim"),
              age:50
         };     
         let emp2 = Employee{
              company:String::from("TutorialsPoint"),
              name:String::from("Kannan"),
              age:32
         };
         //将结构体作为参数传递给display
         display(emp1);
         display(emp2);
    }
    fn display( emp: Employee){
         println!("Name is :{} company is {} age is {}", emp.name, emp.company, emp.age);
    }
    编译运行结果如下
    Name is :Mohtashim company is TutorialsPoint age is 50
    Name is :Kannan company is TutorialsPoint age is 32
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    (四)结构体实例作为函数的返回值
    语法格式

    struct My_struct {}
    fn function_name([parameters]) -> My_struct {
         // 其它的函数逻辑
         return My_struct_instance;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    范例

    fn main() {
         let emp1 = Employee{
              company:String::from("TutorialsPoint"),
              name:String::from("Mohtashim"),
              age:50
         };
         let emp2 = Employee {
              company:String::from("TutorialsPoint"),
              name:String::from("Kannan"),
              age:32
         };
         let elder = who_is_elder(emp1,emp2);
         println!("elder is:");
         display(elder);
    }
    //接受两个Employee的实例作为参数并返回年长的那个
    fn who_is_elder (emp1:Employee,emp2:Employee)->Employee {
         if emp1.age>emp2.age {
              return emp1;
         } else {
              return emp2;
         }
    }
    // 显示结构体的所有元素
    fn display( emp: Employee) {
         println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age);
    }
    // 定义一个结构体
    struct Employee {
         name:String,
         company:String,
         age:u32
    }
    编译运行结果如下
    elder is:
    Name is :Mohtashim company is TutorialsPoint age is 50
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    六、结构体方法

    关联函数是与一个类型相关联的函数。相当于成员函数。
    如果关联函数的第一个参数名为 self,则此关联函数称为方法。
    方法和函数的区别就是,方法是用来操作结构体实例的,而函数则不是。
    为了方便,我们称方法为成员方法,关联函数我们称为成员函数。

    (一)定义
    1.成员方法
    如果你学习过一些面向对象的语言,那你一定很清楚函数一般放在类定义里并在函数中用this表示所操作的实例。
    结构体方法的第一个参数必须是 &self,不需指定类型,因为self是关键字。

    与 C++不同的是,Rust中的结构体方法只能定义在结构体的外面。

    使用 impl 关键字定义结构体,语法格式如下

    struct My_struct {}
    impl My_struct {
         // 定义一个方法
         fn method_name(&self[,other_parameters]) {
             //方法的具体逻辑代码
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结构体impl块可以写多次,效果相当于它们内容的拼接

    结构体方法内部访问结构体字段
    使用 self. 来访问结构体的元素。
    例子

    struct My_struct {
         age: u32
    }
    impl My_struct {
         //定义一个方法
         fn method_name([other_parameters]) {
             self.age = 28;
             println!("{}",self.age);
             //其它的具体逻辑代码
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.成员函数
    成员函数没有 &self参数。
    语法格式如下

    impl Structure_Name {
         fn method_name(param1: datatype, param2: datatype) -> return_type {
             // 方法内部逻辑
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    例子

    #[derive(Debug)]
    struct Rectangle {
        width: u32,
        height: u32,
    }
    impl Rectangle {
        fn create(width: u32, height: u32) -> Rectangle {
            Rectangle { width, height }
        }
    }
    fn main() {
        let rect = Rectangle::create(30, 50);
        println!("{:?}", rect);
    }
    运行结果:
    Rectangle { width: 30, height: 50 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    (二)调用
    1.调用成员方法
    方法可以使用方法调用操作符(.)来调用
    语法格式为

    My_struct.method_name([other_parameters])
    
    • 1

    注意,在调用结构体方法的时候不需要填写self,这个参数的传递Rust编译器会 偷偷的 帮我们完成。

    实例

    struct Rectangle {
        width: u32,
        height: u32,
    }
    impl Rectangle {
        fn area(&self) -> u32 {
            self.width * self.height
        }
    }
    fn main() {
        let rect1 = Rectangle { width: 30, height: 50 };
        println!("rect1's area is {}", rect1.area());
    }
    输出结果:
    rect1's area is 1500
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.调用成员函数
    直接通过结构体名调用,而无需实例。
    使用路径来调用
    语法格式如下

    structure_name::method_name(v1,v2)
    
    • 1

    范例

    //声明结构体Point
    struct Point {
         x: i32,
         y: i32,
    }
    impl Point {
         fn get_instance(x: i32, y: i32) -> Point {
             Point { x: x, y: y }
         }
         fn display(&self){
             println!("x ={} y={}",self.x,self.y );
         }
    }
    fn main(){
         let p1 = Point::get_instance(10,20);
         p1.display();
    }
    编译运行结果如下
    x =10 y=20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    JumpServer未授权访问漏洞 CVE-2023-42442
    队列模拟学习 C++
    Flink之输出算子Redis Sink
    springboot整合redis-sentinel哨兵模式集群(一)
    数组与链表
    HTTP 长连接和 TCP 长连接有什么区别
    [LeetCode周赛复盘] 第 305 场周赛20220807
    How to control the model in the webots usingthe ros controller ?
    java毕业设计毕业生就业信息管理系统Mybatis+系统+数据库+调试部署
    SpringBoot使用Docker并上传至DockerHub
  • 原文地址:https://blog.csdn.net/inxunxun/article/details/132913293