【Rust】第六节:结构体

0 前言

结构体,struct,听到这个名字大家可能会感觉"哇!好熟悉!",毕竟在大学时学习c/cpp的时候已经接触过很多次了,实际上也确实很类似,即使有些不同,比如"所有权系统"(上一节提到了)、"生命周期"(还没提到)、"模式匹配"(也很熟悉吧)、Trait(还没提到),也大多数是在更后面才会提到。

总体来讲,Ruststruct在语法上与c/cpp类似,但因入了一些新的概念和特性,提供更高级、更安全的编程体验,不过这一节只是认识struct,所以学起来会比较轻松。

原文链接:Rust程序设计语言


1 定义与实例化

让我们来定义和实例化一个结构体

rust 复制代码
// 1 定义
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    // 2 实例化
    let user0 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    }; // 整个不可变
    
    // 3 实例化可变
    let mut user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    }; // 整个可变,不能部分可变

    // 4 可变
    user1.email = String::from("anotheremail@example.com");

    // 5 简便实例化
    // 使用结构体更新语法从其他实例创建实例
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1 // 必须放在最后
    };
}

// 6 函数创建
fn build_user(email: String, username: String) -> User {
    User {
        // 7 简洁创建
        email, // 字段初始化的简洁写法
        username,
        active: true,
        sign_in_count: 1,
    }
}

除了以上方式,还可以没有明明字段的方式来创建,比如:

rust 复制代码
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

但是要注意,虽然ColorPoint的内容看起来一样,但他们是不同的类型!如果你一个函数,入参设定为Color,那么不能用Point

不过,有一个比较复杂的内容是,"所有权","可以使结构体存储被其他对象拥有的数据的引用,不过这么做的话需要用上生命周期(lifetime)",这一点内容会在后面笔记中再展开。


2 示例程序

在这一部分,可以注意:

1、结构体定义

2、创建实例

3、impl关联函数

4、多个关联函数

5、非方法

6、dbg调试

7、函数调用,含入参

rust 复制代码
#[derive(Debug)] // 调试
// 结构体
struct Rectangle {
    width: u32,
    height: u32,
}

// 关联函数
impl Rectangle {
    // self使用,注意"&self"
    fn area(&self) -> u32 {
        self.width * self.height
    }
    // 更多的函数
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
// 多个关联函数 is ok
impl Rectangle {
    // 不以self为第一参数的关联函数(不是方法)
    // 因为他们并不作用于一个结构体的实例,而是在类型上定义的,就像`String::from`
    // 需要以结构体名和::语法来调用,见下文
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: sieze,
        }
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    
    dbg!(&rect1); // 如果你对调试有兴趣,请阅读原文
    let rect2 = Rectangle {
        width: 10,
        height: 40,
    };
    let rect3 = Rectangle {
        width: 60,
        height: 45,
    };

    // 方法调用
    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
    // 方法调用、参数传入
    println!("Can rect1 hold rect2 ? {}", rect1.can_hold(&rect2));
    // 不是方法,以此种方式调用
    let sq = Rectangle::square(3);
}
相关推荐
天才奇男子11 分钟前
从零开始搭建Linux Web服务器
linux·服务器·前端
小坏讲微服务11 分钟前
SpringCloud零基础学全栈,实战企业级项目完整使用
后端·spring·spring cloud
长空任鸟飞_阿康29 分钟前
AI 多模态全栈应用项目描述
前端·vue.js·人工智能·node.js·语音识别
Mintopia31 分钟前
🌐 实时协同 AIGC:多人在线 Web 创作的技术架构设计
前端·人工智能·trae
Mintopia33 分钟前
🔥 “Solo Coding”的近期热度解析(截至 2025 年末)
前端·人工智能·trae
humors22136 分钟前
服务端开发案例(不定期更新)
java·数据库·后端·mysql·mybatis·excel
Alberta ゙1 小时前
C++初阶
开发语言·c++
the白勺1 小时前
RabbitMQ-基础-总结
开发语言·c#
顾安r1 小时前
11.14 脚本网页游戏 猜黑红
前端·javascript·游戏·flask·html
码码哈哈0.01 小时前
Vue 3 + Vite 集成 Spring Boot 完整部署指南 - 前后端一体化打包方案
前端·vue.js·spring boot