2024 Rust现代实用教程 Trait特质

news2024/11/5 17:11:56

文章目录

  • 一、Trait特质
  • 二、Trait Object与Box
    • 1.Trait Object
    • 2.dyn关键字
    • 3.Rust中数据传输的三种形式
    • 4.特质与Box
  • 三、Trait Object与泛型
    • 1.泛型与impl不同的写法
    • 2.Multiple Trait Bounds
  • 四、重载操作符Operator
    • 1.Rust重载操作符
    • 2.为结构体实现一个加号的例子
  • 五、Trait与多态和继承
    • 1.Rust并不支持面向对象
    • 2.多态
  • 六、常见的Trait
  • 参考

一、Trait特质

在Rust中,特质(Traits)是一种定义方法签名的机制

  • 特质允许你定义一组方法的签名,但可以不提供具体的实现(也可以提供)。这些方法签名可以包括参数和返回类型,但可以不包括方法的实现代码。

任何类型都可以实现特质,只要它们提供了特质中定义的所有方法。这使得你可以为不同类型提供相同的行为。

特点:

  • 1.内置常量:特质可以内置常量(const),特质中定义的常量在程序的整个生命周期内都是有效的。
  • 2.默认实现:特质可以提供默认的方法实现。如果类型没有为特质中的某个方法提供自定义实现,将会使用默认实现。
  • 3.多重实现:类型可以实现多个特质,这允许你将不同的行为组合在一起。
  • 4.特质边界:在泛型代码中,你可以使用特质作为类型约束。这被称为特质边界,它限制了泛型类型必须实现的特质。
  • 5.TraitAlias:Rust还支持traitalias,允许你为复杂的trait组合创建简洁的别名,以便在代码中更轻松地引l用。

Example:

trait Greeter {
    fn greet(&self);
    fn hello();
}

struct Person {
    name: String,
}

impl Greeter for Person {
    // 为Person 实现greet(&self)
    fn greet(&self) {
        println!("greet {}", self.name);
    }

    fn hello() {
        println!("hello");
    }
}

fn main() {
    let person = Person {
        name: "Yz".to_owned(),
    };
    person.greet();
    Person::hello();
}

编译并运行

 cargo run
   Compiling ch25_trait v0.1.0 (/home/wangji/installer/rust/project/ch25_trait)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.45s
     Running `target/debug/ch25_trait`
greet Yz
hello

二、Trait Object与Box

1.Trait Object

在运行时动态分配的对象

  • “运行时泛型”
  • 比泛型要灵活的多

2可以在集合中混入不同的类型对象

  • 更容易处理相似的数据

3.有一些小小的性能损耗

2.dyn关键字

dyn 是 Rust中的关键字,用于声明特质对象(trait object)的类型。特质对象是实现了特定特质(trait)的类型的实例,但其具体类型在编译时是未知的。

因此,为了让编译器知道我们正在处理的是特质对象,我们需要在特质名称前面加上 dyn 关键字。

dyn关键字的作用是指示编译器处理特质对象。

3.Rust中数据传输的三种形式

不可变引l用(Immutable References)

  • &dyn Trait

可变引l用 (Mutable References)

  • &mut dyn Trait

Move语义所有权转移

  • 特质需要用Box<dyn Trait>实现move,如果你需要在函数调用之间传递特质的所有权,并且希望避免在栈上分配大量的内存,可以使用 Box<dyn Trait>。

4.特质与Box

创建trait Object的三种方式
第一种

let o = Object{};
let o_obj: &dyn Object = &o;

第二种

let o_obj: &dyn Object = &0bject{};

第三种

let o_obj: Box<dyn Object> = Box::new(Object {}) ;

第一种和第二种都是创建不可变引用
第三种最常用也最灵活,一般来说会使用Box和特质来组成集合元素

// trait 不可变引用 \ Move
struct Obj {}
trait Overview {
    fn overview(&self) -> String {
        String::from("overview")
    }
}

impl Overview for Obj {
    fn overview(&self) -> String {
        String::from("Obj")
    }
}
// 不可变引用
fn call_obj(item: &impl Overview) {
    println!("Overview {}", item.overview());
}
// Move
fn call_obj_box(item: Box<dyn Overview>) {
    println!("Overview {}", item.overview());
}

trait Sale {
    fn amount(&self) -> f64;
}

// 元组结构体
struct Common(f64);
impl Sale for Common {
    fn amount(&self) -> f64 {
        self.0
    }
}

struct TenDiscount(f64);
impl Sale for TenDiscount {
    fn amount(&self) -> f64 {
        self.0 - 10.0
    }
}

struct TenPercentDiscount(f64);
impl Sale for TenPercentDiscount {
    fn amount(&self) -> f64 {
        self.0 * 0.9
    }
}

fn calculate(sales: &Vec<Box<dyn Sale>>) -> f64 {
    sales.iter().map(|sale| sale.amount()).sum()
}

fn main() {
    let a = Obj {};
    call_obj(&a);
    println!("{}", a.overview());
    let b_a = Box::new(Obj {});
    call_obj_box(b_a);
    // println!("{}", b_a.overview());

    /**
    等价写法
    let c:  = Box::new(Common(100.0));
    let t1:  = Box::new(TenDiscount(100.0));
    let t2: Vec<Box<dyn Sale>> = Box::new(TenPercentDiscount(200.0));

    let sales:  = vec![c, t1, t2]; // : Vec<Box<dyn Sale>>

     */
    let c: Box<dyn Sale> = Box::new(Common(100.0));
    let t1: Box<dyn Sale> = Box::new(TenDiscount(100.0));
    let t2: Box<dyn Sale> = Box::new(TenPercentDiscount(200.0));

    let sales = vec![c, t1, t2]; // : Vec<Box<dyn Sale>>

    println!("pay {}", calculate(&sales));
}

编译及运行:

 cargo run
   Compiling ch26_trait_box v0.1.0 (/home/wangji/installer/rust/project/ch26_trait_box)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s
     Running `target/debug/ch26_trait_box`
Overview Obj
Obj
Overview Obj
pay 370
~/installer/rust/project/ch26_trait_box master 
 cargo run
   Compiling ch26_trait_box v0.1.0 (/home/wangji/installer/rust/project/ch26_trait_box)
warning: unused doc comment
  --> src/main.rs:61:5
   |
61 | /     /**
62 | |     等价写法
63 | |     let c: Box<dyn Sale> = Box::new(Common(100.0));
64 | |     let t1: Box<dyn Sale> = Box::new(TenDiscount(100.0));
...  |
68 | |
69 | |      */
   | |_______^
70 |       let c: Box<dyn Sale> = Box::new(Common(100.0));
   |       ----------------------------------------------- rustdoc does not generate documentation for statements
   |
   = help: use `/* */` for a plain comment
   = note: `#[warn(unused_doc_comments)]` on by default

warning: `ch26_trait_box` (bin "ch26_trait_box") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.28s
     Running `target/debug/ch26_trait_box`
Overview Obj
Obj
Overview Obj
pay 370

三、Trait Object与泛型

1.泛型与impl不同的写法

fn call(item1: &impl Trait, item2: &impl Trait) ;
可以是不同类型

fn call_generic<T: Trait>(item1: &T, item2: &T) ;
必须是相同类型

2.Multiple Trait Bounds

fn call(item1: & (impl Trait+ AnotherTrait) );
fn call_generic<T: Trait+ AnotherTrait>(item1: &T);

Example:

trait Overview {
    fn overview(&self) -> String {
        String::from("Course")
    }
}

trait Another {
    fn hell(&self) {
        println!("welcome to hell");
    }
}

struct Course {
    headline: String,
    author: String,
}

impl Overview for Course {}
impl Another for Course {}

struct AnotherCourse {
    headline: String,
    author: String,
}

impl Overview for AnotherCourse {}

// 写法1:入参类型:&impl Overview
fn call_overview(item: &impl Overview) {
    println!("Overview {}", item.overview());
}

// 写法2:指定模板参数是T: Overview
fn call_overview_generic<T: Overview>(item: &T) {
    println!("Overview {}", item.overview());
}

fn call_overviewT(item: &impl Overview, item1: &impl Overview) {
    println!("Overview {}", item.overview());
    println!("Overview {}", item1.overview());
}

fn call_overviewTT<T: Overview>(item: &T, item1: &T) {
    println!("Overview {}", item.overview());
    println!("Overview {}", item1.overview());
}
// 多绑定写法1
fn call_mul_bind(item: &(impl Overview + Another)) {
    println!("Overview {}", item.overview());
    item.hell();
}

// 多绑定写法2
fn call_mul_bind_generic<T: Overview + Another>(item: &T) {
    println!("Overview {}", item.overview());
    item.hell();
}

// 多绑定写法3
fn call_mul_bind_generic_generic<T>(item: &T)
where
    T: Overview + Another,
{
    println!("Overview {}", item.overview());
    item.hell();
}

fn main() {
    let c0 = Course {
        headline: "ff".to_owned(),
        author: "yy".to_owned(),
    };
    let c1 = Course {
        headline: "ff".to_owned(),
        author: "yy".to_owned(),
    };

    let c2 = AnotherCourse {
        headline: "ff".to_owned(),
        author: "yz".to_owned(),
    };
    // call_overview(&c1);
    // call_overview_generic(&c1);
    // call_overviewT(&c1, &c2);
    // println!("-------------------");
    // call_overviewTT(&c1, &c0);
    // call_overviewT(&c1, &c0);
    call_mul_bind(&c1);
    call_mul_bind_generic(&c1);
}

编译及运行:

 cargo run
warning: unused variable: `c0`
  --> src/main.rs:69:9
   |
69 |     let c0 = Course {
   |         ^^ help: if this is intentional, prefix it with an underscore: `_c0`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `c2`
  --> src/main.rs:78:9
   |
78 |     let c2 = AnotherCourse {
   |         ^^ help: if this is intentional, prefix it with an underscore: `_c2`

warning: fields `headline` and `author` are never read
  --> src/main.rs:14:5
   |
13 | struct Course {
   |        ------ fields in this struct
14 |     headline: String,
   |     ^^^^^^^^
15 |     author: String,
   |     ^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: fields `headline` and `author` are never read
  --> src/main.rs:22:5
   |
21 | struct AnotherCourse {
   |        ------------- fields in this struct
22 |     headline: String,
   |     ^^^^^^^^
23 |     author: String,
   |     ^^^^^^

warning: function `call_overview` is never used
  --> src/main.rs:29:4
   |
29 | fn call_overview(item: &impl Overview) {
   |    ^^^^^^^^^^^^^

warning: function `call_overview_generic` is never used
  --> src/main.rs:34:4
   |
34 | fn call_overview_generic<T: Overview>(item: &T) {
   |    ^^^^^^^^^^^^^^^^^^^^^

warning: function `call_overviewT` is never used
  --> src/main.rs:38:4
   |
38 | fn call_overviewT(item: &impl Overview, item1: &impl Overview) {
   |    ^^^^^^^^^^^^^^

warning: function `call_overviewTT` is never used
  --> src/main.rs:43:4
   |
43 | fn call_overviewTT<T: Overview>(item: &T, item1: &T) {
   |    ^^^^^^^^^^^^^^^

warning: function `call_mul_bind_generic_generic` is never used
  --> src/main.rs:60:4
   |
60 | fn call_mul_bind_generic_generic<T>(item: &T)
   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: function `call_overviewT` should have a snake case name
  --> src/main.rs:38:4
   |
38 | fn call_overviewT(item: &impl Overview, item1: &impl Overview) {
   |    ^^^^^^^^^^^^^^ help: convert the identifier to snake case: `call_overview_t`
   |
   = note: `#[warn(non_snake_case)]` on by default

warning: function `call_overviewTT` should have a snake case name
  --> src/main.rs:43:4
   |
43 | fn call_overviewTT<T: Overview>(item: &T, item1: &T) {
   |    ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `call_overview_tt`

warning: `ch27_trait_generic` (bin "ch27_trait_generic") generated 11 warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/ch27_trait_generic`
Overview Course
welcome to hell
Overview Course
welcome to hell

四、重载操作符Operator

1.Rust重载操作符

只需要实现相应的特质

2.为结构体实现一个加号的例子

use std::ops::Add;

// 编译时
//#[derive(Debug)] 实现Debug打印的特质
/**
 * #[derive(Debug)]
 * 等价于
 * impl Debug for Point {...}
 * 
 * 
 */
#[derive(Debug)]
struct Point<T> {
    x: T,
    y: T,
}

// T的这样类型 它可以执行相加的操作
impl<T> Add for Point<T>
where
    T: Add<Output = T>,
{
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Point {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

fn main() {
    let i1 = Point { x: 1, y: 2 };
    let i2 = Point { x: 1, y: 3 };
    let sum = i1 + i2;
    println!("{:?}", sum);//#[derive(Debug)]
    let f1 = Point { x: 1.0, y: 2.2 };
    let f2 = Point { x: 1.0, y: 3.0 };
    let sum = f1 + f2;
    println!("{:?}", sum);
}

编译及运行

▶ cargo run
   Compiling ch1_add v0.1.0 (/home/wangji/code/rust/2024_rust/rust_project/ch1_add)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.09s
     Running `target/debug/ch1_add`
Point { x: 2, y: 5 }
Point { x: 2.0, y: 5.2 }

五、Trait与多态和继承

1.Rust并不支持面向对象

Rust并不支持传统的继承的概念,但是你可以在特质中通过层级化来完成你的需求
Rust选择了一种函数式的编程范式,即"组合和委托"而非"继承"
编程语言的大势也是组合优于继承

2.多态

多态是面向对象编程中的一个重要概念,指的是同一个方法调用可以根据对象的不同类型而表现出不同的行为。简单来说,多态允许一个接口或方法在不同的上下文中表现出不同的行为。这样做的好处是可以提高代码的灵活性和可扩展性,使得代码更易于维护和理解

Rust中的多态无处不在

use std::collections::VecDeque;
// 多态
trait Driver {
    fn drive(&self);
}
struct Car;
impl Driver for Car {
    fn drive(&self) {
        println!("Car is driving");
    }
}

struct SUV;
impl Driver for SUV {
    fn drive(&self) {
        println!("SUV is driving");
    }
}

fn road(vehicle: &dyn Driver) {
    vehicle.drive();
}
// 继承思想:针对于特质
// 单向特质
trait Queue {
    fn len(&self) -> usize;
    fn push_back(&mut self, n: i32);//后面加入
    fn pop_front(&mut self) -> Option<i32>;//前面移除
}

// 双向特质
trait Deque: Queue {
    fn push_front(&mut self, n: i32);//从前面加入
    fn pop_back(&mut self) -> Option<i32>;//从后面移除
}

#[derive(Debug)]
struct List {
    data: VecDeque<i32>,
}

impl List {
    fn new() -> Self {
        let data = VecDeque::<i32>::new();
        Self { data }
    }
}

impl Deque for List {
    fn push_front(&mut self, n: i32) {
        self.data.push_front(n)
    }

    fn pop_back(&mut self) -> Option<i32> {
        self.data.pop_back()
    }
}

impl Queue for List {
    fn len(&self) -> usize {
        self.data.len()
    }

    fn push_back(&mut self, n: i32) {
        self.data.push_back(n)
    }

    fn pop_front(&mut self) -> Option<i32> {
        self.data.pop_front()
    }
}

fn main() {
    // road(&Car);
    // road(&SUV);

    let mut l = List::new();
    l.push_back(1);
    l.push_front(0);
    println!("{:?}", l);
    l.push_front(2);
    println!("{:?}", l);
    l.push_back(2);
    println!("{:?}", l);
    println!("{}", l.pop_back().unwrap());
    println!("{:?}", l);
}

编译及运行

▶ cargo run
   Compiling ch2_trai v0.1.0 (/home/wangji/code/rust/2024_rust/rust_project/ch2_trai)
warning: trait `Driver` is never used
 --> src/main.rs:3:7
  |
3 | trait Driver {
  |       ^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: struct `Car` is never constructed
 --> src/main.rs:6:8
  |
6 | struct Car;
  |        ^^^

warning: struct `SUV` is never constructed
  --> src/main.rs:13:8
   |
13 | struct SUV;
   |        ^^^

warning: function `road` is never used
  --> src/main.rs:20:4
   |
20 | fn road(vehicle: &dyn Driver) {
   |    ^^^^

warning: methods `len` and `pop_front` are never used
  --> src/main.rs:26:8
   |
25 | trait Queue {
   |       ----- methods in this trait
26 |     fn len(&self) -> usize;
   |        ^^^
27 |     fn push_back(&mut self, n: i32);
28 |     fn pop_front(&mut self) -> Option<i32>;
   |        ^^^^^^^^^

warning: `ch2_trai` (bin "ch2_trai") generated 5 warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.61s
     Running `target/debug/ch2_trai`
List { data: [0, 1] }
List { data: [2, 0, 1] }
List { data: [2, 0, 1, 2] }
2
List { data: [2, 0, 1] }

六、常见的Trait

// 常见的trait:Debug Clone Copy PartialEq
// 层级
/**
 * #[derive(Debug)]等价于
 * impl Debug for XXX {}
 * 
 * 
 * 特质Copy表示能够拷贝,而不是移动
 */
#[derive(Debug, Clone, Copy)]
enum Race {
    White,
    Yellow,
    Black,
}
impl PartialEq for Race {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Race::White, Race::White) => true,
            (Race::Yellow, Race::Yellow) => true,
            (Race::Black, Race::Black) => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone)]
struct User {
    id: u32,
    name: String,
    race: Race,
}

impl PartialEq for User {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id && self.name == other.name && self.race == other.race
    }
}

fn main() {
    let user = User {
        id: 3,
        name: "John".to_owned(),
        race: Race::Yellow,
    };
    println!("{:?}", user);//enum Race和struct User都得实现Debug特质,才能打印出来
    let user2 = user.clone();//Clone特质
    println!("{:#?}", user2);
    println!("{}", user == user2);
}

编译及运行:

▶ cargo run
   Compiling ch63_trait_common v0.1.0 (/home/wangji/code/rust/2024_rust/rust_project/ch3_trait_common)
warning: variants `White` and `Black` are never constructed
 --> src/main.rs:5:5
  |
4 | enum Race {
  |      ---- variants in this enum
5 |     White,
  |     ^^^^^
6 |     Yellow,
7 |     Black,
  |     ^^^^^
  |
  = note: `Race` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis
  = note: `#[warn(dead_code)]` on by default

warning: `ch63_trait_common` (bin "ch63_trait_common") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/ch63_trait_common`
User { id: 3, name: "John", race: Yellow }
User {
    id: 3,
    name: "John",
    race: Yellow,
}

参考

  • 2024 Rust现代实用教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2233701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp+vite配置环境变量

文章目录 前言一、配置变量二、定义变量生效三、脚本执行使其生效使用 总结如有启发&#xff0c;可点赞收藏哟~ 前言 查看官方文档 由于官方提示不支持在package.json配置脚本 --mode xx&#xff08;实际H5是可以的&#xff0c;但是在微信小程序等使用import.meta.env就会报错…

#Prompt | AI | LLM # 人类如何写出LLM理解的Prompt

一、如何写好Prompt 结构化Prompt 结构化Prompt是对信息进行组织&#xff0c;使其遵循特定模式和规则&#xff0c;以便于有效理解信息。常用模块包括&#xff1a; Role: 指定角色&#xff0c;使模型聚焦于特定领域。Profile: 包括作者、版本、语言和描述。Goals: 描述Prompt的…

Qt项目实战:红绿灯小程序

目录 一.初始化对象 二.捕获并处理特定的事件 三.自定义绘制方法 四.绘制外部边框 五.绘制内部边框 六.绘制按钮的背景色 七.绘制覆盖层&#xff08;高光效果&#xff09; 八.效果 九.代码 1.h 2.cpp 一.初始化对象 1.设置文本、颜色、边框和背景色等默认值。 2.安…

九泰智库 | 医械周刊- Vol.66

⚖️ 法规动态 北京视觉科学与转化医学研究中心正式成立 北京视觉科学与转化医学研究中心&#xff08;BERI&#xff09;于2024年10月26日在清华大学成立&#xff0c;旨在深入贯彻党的二十届三中全会精神&#xff0c;助力健康中国建设&#xff0c;推动全球视觉健康事业发展。该…

我谈正态分布——正态偏态

目录 pdf和cdf参数 标准正态分布期望和方差分布形态 3 σ 3\sigma 3σ原则 正态和偏态正态偏态瑞利分布偏度 (Skewness)峰度 (Kurtosis) 比较 正态分布的英文是Normal Distribution&#xff0c;normal是“正常”或“标准”的意思&#xff0c;中文翻译是正态&#xff0c;多完美的…

Web服务器(理论)

目录 Web服务器www简介常见Web服务程序介绍&#xff1a;服务器主机主要数据浏览器 网址及HTTP简介URLhttp请求方法:2.3 HTTP协议请求的工作流程&#xff1a; www服务器的类型静态网站动态网站 HTTPS简介概念解释SSL协议分为两层SSL协议提供的服务 HTTPS安全通信机制图解过程 快…

解决方案 | 部署更快,自动化程度高!TOSUN同星线控底盘解决方案

Tosun——线控底盘解决方案 在汽车智能化和电动化进程中&#xff0c;智能线控底盘相关的核心技术和产品成为了新能源汽车及智能驾驶产业的重点发展方向。同星智能作为行业先行者&#xff0c;精研汽车电子行业整体解决方案&#xff0c;提供基于TSMaster的底盘HIL仿真测试解决方…

服务器作业(2)

架设一台NFS服务器&#xff0c;并按照以下要求配置 关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 配置文件设置&#xff1a; [rootlocalhost ~]# vim /etc/exports 1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 共享…

架构师备考-软件工程相关补充

目录 软件开发生命周期 软件工程过程 软件维护分类 遗留系统 软件重用 逆向工程 相关概念 抽象层次 需求工程 需求工程主要活动 需求管理的主要活动 需求获取的主要步骤 需求获取方法 需求变更管理的过程 净室软件工程 定义 理论基础 技术手段 应用 缺点 软…

基于SSM+VUE小型企业财务报销管理系统JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

站大爷代理IP工具的导入功能介绍

在数字化时代&#xff0c;代理IP成为了网络爬虫、数据挖掘等网络活动中不可或缺的工具。站大爷代理IP工具深刻理解用户的需求&#xff0c;提供了多种代理IP导入方式&#xff0c;让代理IP的管理变得简单高效。下面就来详细了解一下这些便捷的导入方法&#xff1a; 一、站大爷AP…

CSP-J2023T4 旅游巴士(同余最短路)

题目链接&#xff1a;https://www.luogu.com.cn/problem/P9751 题意&#xff1a;给定 n 个点&#xff0c; m 条单向边&#xff0c;一个时间间隔 k 。有这样一些限制条件&#xff1a; 1&#xff09;1号点是入口&#xff0c; n 号点是出口&#xff1b; 2&#xff09;经过一条边…

React系列教程(2)React哲学

豆约翰习惯将掌握某一技术分为5个层次&#xff1a;初窥门径&#xff0c;小试牛刀&#xff0c;渐入佳境&#xff0c;得心应手&#xff0c;玩转自如 本篇属于React框架中的第1层次即初窥门径 我们认为&#xff0c;React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方…

「Mac畅玩鸿蒙与硬件29」UI互动应用篇6 - 多选问卷小应用

本篇将带你实现一个多选问卷小应用&#xff0c;用户可以勾选选项并点击提交按钮查看选择的结果。通过本教程&#xff0c;你将学习如何使用 Checkbox 组件、动态渲染列表、状态管理及用户交互&#xff0c;构建完整的应用程序。 关键词 UI互动应用Checkbox 组件状态管理动态列表…

【linux 多进程并发】0203 网络资源的多进程处理,子进程完全继承网络套接字,避免“惊群”问题

0203 网络资源的多进程处理 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 一、概…

江协科技STM32学习- P32 MPU6050

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

程序设计方法与实践-时空权衡

什么是时空权衡&#xff1f; 时空权衡是算法设计中的一个众所周知的问题&#xff0c;也就是对算法的空间和时间效率做出权衡&#xff0c;它大概有分两种形式&#xff1a; 对输入的部分数据或者全部数据作预处理&#xff0c;然后对于获得额外信息储存起来&#xff0c;从而加快…

STM32F1学习——TIM

一、STM32中的定时器 在STM32中分为三种定时器&#xff0c;分别是基本定时器&#xff0c;通用定时器和高级定时器&#xff0c;每种定时器都是向下兼容的。 二、定时器详细介绍 a、基本定时器 基本定时器主要由下面与分频器、计数器 和 自动重装寄存器三个组成的时基单元&#…

W5500-EVB-Pico2评估板介绍

目录 1 概述 2 板载资源 2.1 硬件规格 2.2 硬件规格 2.3 工作条件 3 参考资料 3.1 RP2350 数据手册 3.2 W5500 数据手册 3.3 原理图 原理图 & 物料清单 & Gerber 文件 3.3 尺寸图 (单位 : mm) 3.4 参考例程 认证 CE FCC AWS 资质 Microsoft Azure 认证…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十二:在屏幕上显示多路视频播放,可以有不同的分辨率,格式和帧率。

上图是在安防领域的要求&#xff0c;一般都是一个屏幕上有显示多个摄像头捕捉到的画面&#xff0c;这一节&#xff0c;我们是从文件中读取多个文件&#xff0c;显示在屏幕上。