Rust 程序设计语言学习——泛型、Trait和生命周期
创作时间:
作者:
@小白创作中心
Rust 程序设计语言学习——泛型、Trait和生命周期
引用
CSDN
1.
https://blog.csdn.net/tyyj90/article/details/140032029
Rust是一门系统级编程语言,以其内存安全和并发安全著称。在Rust中,泛型、Trait和生命周期是三个核心概念,它们共同帮助开发者编写更安全、更灵活的代码。本文将详细介绍这些概念的基本原理、使用方法和实际应用,通过具体的代码示例帮助读者理解。
一、泛型
泛型是Rust中处理重复概念的重要工具。通过泛型,我们可以为函数签名或结构体创建定义,使其能够用于多种不同的具体数据类型。
1.1 在函数定义中使用泛型
在函数签名中使用泛型,可以使得代码更具适应性和复用性。例如:
fn add_impl<T>(num1: T, num2: T) -> T
where
T: std::ops::Add<Output = T> + Copy,
{
num1 + num2
}
fn main() {
let a = 3.0f32;
let b = 4.5f32;
let ret = add_impl(a, b);
println!("The result of {} + {} is {}", a, b, ret);
let a1 = 3;
let b1 = 4;
let ret1 = add_impl(a1, b1);
println!("The result of {} + {} is {}", a1, b1, ret1);
}
运行结果
The result of 3 + 4.5 is 7.5
The result of 3 + 4 is 7
1.2 结构体、方法定义中的泛型
同样可以在结构体中使用泛型,以创建更灵活的数据结构。例如:
struct Box<T> {
width: T,
height: T,
}
impl<T> Box<T> {
fn area(&self) -> T
where
T: std::ops::Mul<Output = T> + Copy,
{
self.width * self.height
}
}
impl<T> Box<T> {
fn new(width: T, height: T) -> Self {
Box { width, height }
}
}
fn main() {
let int_box = Box::new(10, 20);
println!("The area of the integer box is: {}", int_box.area());
let float_box = Box::new(10.5, 20.3);
println!("The area of the float box is: {}", float_box.area());
}
运行结果
The area of the integer box is: 200
The area of the float box is: 213.15
1.3 枚举定义中的泛型
枚举也可以包含泛型数据类型。例如标准库中的Option<T>枚举:
enum Option<T> {
Some(T),
None,
}
1.4 泛型代码的性能
Rust通过编译时的单态化(monomorphization)过程来优化泛型代码的性能。例如:
let integer = Some(5);
let float = Some(5.0);
编译器会生成类似以下的单态化代码:
enum Option_i32 {
Some(i32),
None,
}
enum Option_f64 {
Some(f64),
None,
}
fn main() {
let integer = Option_i32::Some(5);
let float = Option_f64::Some(5.0);
}
二、Trait
Trait类似于其他语言中的接口,用于定义类型的行为。例如:
pub trait Animal {
fn speak(&self);
fn name(&self) -> &str;
}
struct Dog {
name: String,
}
impl Animal for Dog {
fn speak(&self) {
println!("Woof!");
}
fn name(&self) -> &str {
&self.name
}
}
struct Cat {
name: String,
}
impl Animal for Cat {
fn speak(&self) {
println!("Meow!");
}
fn name(&self) -> &str {
&self.name
}
}
fn animal_sound<T: Animal>(animal: &T) {
println!("{} says: ", animal.name());
animal.speak();
}
fn main() {
let dog = Dog {
name: "Rex".to_string(),
};
let cat = Cat {
name: "Whiskers".to_string(),
};
animal_sound(&dog);
animal_sound(&cat);
}
运行结果
Rex says:
Woof!
Whiskers says:
Meow!
三、生命周期
生命周期是Rust中确保引用安全的重要机制。例如:
fn main() {
let a;
{
let b = 1;
a = &b;
println!("a: {a} b: {b}");
}
println!("a: {a}");
}
编译报错信息:
Compiling playground v0.0.1 (/playground)
error[E0597]: `b` does not live long enough
--> src/main.rs:6:13
|
5 | let b = 1;
| - binding `b` declared here
6 | a = &b;
| ^^ borrowed value does not live long enough
7 | println!("a: {a} b: {b}");
8 | }
| - `b` dropped here while still borrowed
9 |
10 | println!("a: {a}");
| --- borrow later used here
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` (bin "playground") due to 1 previous error
3.1 生命周期避免了悬垂引用
生命周期的主要目标是避免悬垂引用。例如:
fn main() {
let a; //---------+-- 'a
// |
{ // |
let b = 1; //-+-- 'b |
a = &b; // | |
println!("a: {a} b: {b}"); // | |
} //-+ |
// |
println!("a: {a}"); // |
} //---------+
3.2 函数中的泛型生命周期
例如:
fn max<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
if (*x) > (*y) {
x
} else {
y
}
}
fn main() {
let a = 10;
let b = 20;
println!("max: {}", max(&a, &b));
}
运行结果
max: 20
3.3 函数签名中的生命周期注解
生命周期注解的语法:
&i32 // 引用
&'a i32 // 带有显式生命周期的引用
&'a mut i32 // 带有显式生命周期的可变引用
3.4 结构体和方法定义中的生命周期注解
例如:
struct Message<'a> {
content: &'a str,
}
impl<'a> Message<'a> {
fn print(&self) {
println!("The message is: {}", self.content);
}
}
fn main() {
let text = "Hello, Rust!".to_string();
let message = Message { content: &text };
message.print();
}
运行结果
The message is: Hello, Rust!
3.5 生命周期省略
Rust编译器采用三条规则来判断引用何时不需要明确的注解:
- 每个引用参数都分配一个生命周期参数。
- 如果只有一个输入生命周期参数,它被赋予所有输出生命周期参数。
- 如果方法有多个输入生命周期参数并且其中一个参数是
&self或&mut self,则所有输出生命周期参数被赋予self的生命周期。
3.6 静态生命周期
例如:
let s: &'static str = "I have a static lifetime.";
3.7 结合泛型类型参数、trait bounds 和生命周期
例如:
trait Append {
fn append(&mut self, other: &str);
}
impl Append for String {
fn append(&mut self, other: &str) {
self.push_str(other);
}
}
struct Appender<'a, T: Append> {
item: &'a mut T,
}
impl<'a, T: Append> Appender<'a, T> {
fn add_content(&mut self, other: &str) {
self.item.append(other);
}
}
fn main() {
let mut text = String::from("Hello, ");
let mut appender = Appender { item: &mut text };
appender.add_content("world!");
println!("{}", text);
}
运行结果
Hello, world!
参考链接
- Rust 官方网站:https://www.rust-lang.org/zh-CN
- Rust 官方文档:https://doc.rust-lang.org/
- Rust Play:https://play.rust-lang.org/
- 《Rust 程序设计语言》
热门推荐
探究刘备的身世:刘弘之子的争议与历史考证
三国正史中,真正能够以一敌百的猛将只有4位,他们分别是谁?
刘备若迎汉献帝:可能性与历史背景探析
一周涨幅近1000%!特朗普与“散户之王”联手带飞meme币
济南必吃的8种绝世美食,看看你尝过几种?
济南餐饮品牌,美食之都的繁华与魅力
心理学上有一个词叫:标签效应
最新研究发现:有这8个习惯的人,更容易长寿
决定人寿命长短的,不只是吃和运动,还有这些关键因素
喝咖啡真的会升高血压吗?最新研究给出答案
心血管专家推荐:高血压患者的咖啡饮用指南
心血管专家王医生:高血压患者如何健康饮咖啡?
退休后工作就不算“劳动者”了,劳动权益如何保障?
民办职业培训机构办学资格申请需要哪里条件才能审批?
湖南花鼓戏:元旦节庆中的文化传承与创新
沔阳花鼓戏:地域特色的传承与创新
湖南花鼓戏:在传承与创新中绽放新光彩
花鼓戏唱词的特色解析:以湖南、湖北、安徽为例
湖南花鼓戏:文化瑰宝中的独特魅力
《钢铁是怎样炼成的》第一章第二章内容概括和阅读感受
秋冬护骨新趋势:科学预防股骨再伤
股骨骨折术后康复:科学锻炼助你快速恢复!
股骨干骨折术后康复新趋势:从干细胞技术到传统训练
二甲双胍新发现:抗糖尿病还能缓解焦虑?
湖南花鼓戏:从田间地头到文旅新宠
冬日打卡:西塔大冷面,排队也要吃的美味!
红烧肉的英文表达你get了吗?
矿泉水版东北大冷面,夏日清凉必备!
解密哈尔滨烤冷面走红:从街头小吃到国民爆款
从“烧”字说起:正确烹饪保障饮食安全