Rust面试题及详细答案120道(11-18)-- 控制流与函数
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 11. Rust的`if`表达式与其他语言的`if`语句有何不同?(提示:返回值)
- 12. 简述`loop`、`while`、`for`循环的使用场景,如何退出循环?
- 1. `loop`:无限循环
- 2. `while`:条件循环
- 3. `for`:迭代循环
- 13. `break`和`continue`在循环中的作用,`break`如何返回值?
- 1. `break`的作用
- 2. `continue`的作用
- 14. 函数的参数和返回值在Rust中如何定义?返回值可以省略`return`吗?
- 1. 参数定义
- 2. 返回值定义
- 3. 返回值与`return`的关系
- 15. 什么是表达式(Expression)和语句(Statement)?Rust中函数体的本质是什么?
- 1. 表达式(Expression)
- 2. 语句(Statement)
- 3. 函数体的本质
- 16. 如何定义一个没有返回值的函数?(提示:`()`单元类型)
- 1. 省略返回值类型声明
- 2. 显式声明返回`()`
- 17. 函数可以嵌套定义吗?Rust的作用域规则是什么?
- 1. 函数嵌套定义
- 2. 作用域规则
- 18. 举例说明函数参数的模式匹配(如解构元组、结构体)。
- 1. 解构元组参数
- 2. 解构结构体参数
- 3. 解构枚举参数
- 二、120道Rust面试题目录列表
一、本文面试题目录
11. Rust的if
表达式与其他语言的if
语句有何不同?(提示:返回值)
Rust的if
是表达式(Expression),而非单纯的语句(Statement),这是它与其他语言(如C、Java)中if
语句的核心区别。
- 关键差异:Rust的
if
表达式可以返回值,且所有分支的返回值类型必须一致。 - 原理:在Rust中,表达式会产生一个值,而语句(如
let
声明)不产生值(或说返回()
)。if
表达式的返回值由各分支的最后一个表达式决定。
示例:
// if表达式返回值
let num = 5;
let result = if num > 0 {"positive" // 分支最后一个表达式(无分号)作为返回值
} else if num < 0 {"negative"
} else {"zero"
};
println!("{}", result); // 输出:positive// 若分支加了分号,返回单元类型()
let val = if num > 0 {10; // 语句,返回()
} else {20;
};
println!("{:?}", val); // 输出:()
其他语言中if
仅用于控制流程,无法直接返回值(需借助变量赋值),而Rust的if
表达式更简洁地支持这一功能。
12. 简述loop
、while
、for
循环的使用场景,如何退出循环?
Rust提供三种循环类型,适用场景和退出方式不同:
1. loop
:无限循环
- 场景:需要无限重复执行,直到满足特定条件才退出(如服务器监听请求、重试逻辑)。
- 退出方式:必须使用
break
手动退出,可配合条件判断。
示例:
let mut count = 0;
loop {count += 1;if count == 3 {break; // 满足条件退出循环}println!("count: {}", count); // 输出:1 2
}
2. while
:条件循环
- 场景:当循环条件为
true
时执行,适合循环次数不确定的场景(如处理用户输入直到退出指令)。 - 退出方式:条件为
false
时自动退出,也可使用break
强制退出。
示例:
let mut n = 3;
while n > 0 {println!("n: {}", n); // 输出:3 2 1n -= 1;if n == 1 {break; // 提前退出}
}
3. for
:迭代循环
- 场景:遍历集合(如数组、范围、迭代器),循环次数由集合长度决定,是Rust中最常用的循环。
- 退出方式:遍历完所有元素自动退出,也可使用
break
强制退出。
示例:
// 遍历范围
for i in 1..4 {println!("i: {}", i); // 输出:1 2 3
}// 遍历数组
let arr = [10, 20, 30];
for val in arr {println!("val: {}", val); // 输出:10 20 30if val == 20 {break; // 提前退出}
}
总结:loop
用于无限循环,while
用于条件控制,for
用于迭代集合,三者均可通过break
强制退出。
13. break
和continue
在循环中的作用,break
如何返回值?
break
和continue
是循环控制的核心关键字,功能如下:
1. break
的作用
- 立即终止当前循环,并跳出循环体。
- 特殊能力:在
loop
循环中,break
可以返回一个值(该值成为loop
表达式的结果)。
示例:break
返回值
let mut sum = 0;
let result = loop {sum += 5;if sum >= 20 {break sum; // 返回sum的值并退出循环}
};
println!("Result: {}", result); // 输出:20(sum=5+5+5+5=20)
2. continue
的作用
- 跳过当前循环的剩余部分,直接进入下一次循环。
- 不终止循环,仅跳过当前迭代。
示例:continue
跳过迭代
for i in 1..6 {if i % 2 == 0 {continue; // 跳过偶数}println!("i: {}", i); // 输出:1 3 5
}
区别总结:
关键字 | 作用 | 适用循环类型 |
---|---|---|
break | 终止循环,可返回值(仅loop 中) | loop /while /for |
continue | 跳过当前迭代,进入下一次循环 | loop /while /for |
14. 函数的参数和返回值在Rust中如何定义?返回值可以省略return
吗?
Rust函数的参数和返回值定义有严格的语法规则,且支持灵活的返回值处理。
1. 参数定义
- 函数参数需显式声明类型,格式为
参数名: 类型
。 - 多个参数用逗号分隔。
示例:
// 两个i32类型参数的函数
fn add(a: i32, b: i32) -> i32 {a + b
}
2. 返回值定义
- 通过
-> 类型
在函数签名末尾声明返回值类型。 - 若函数无返回值,可省略
-> 类型
(默认返回()
)。
3. 返回值与return
的关系
- 可以省略
return
:函数体中最后一个表达式的结果会自动作为返回值(表达式后不加分号)。 return
的作用:用于提前返回值(如在条件判断中)。
示例:
// 省略return,最后一个表达式作为返回值
fn multiply(x: i32, y: i32) -> i32 {x * y // 无分号,表达式结果作为返回值
}// 使用return提前返回
fn absolute_value(n: i32) -> i32 {if n < 0 {return -n; // 提前返回}n // 最后一个表达式返回
}println!("{}", multiply(3, 4)); // 输出:12
println!("{}", absolute_value(-5)); // 输出:5
注意:若最后一个表达式后加了分号,会被视为语句,返回值变为()
(单元类型),可能导致类型不匹配错误。
15. 什么是表达式(Expression)和语句(Statement)?Rust中函数体的本质是什么?
在Rust中,表达式和语句是两个核心概念,决定了代码的执行逻辑和返回值。
1. 表达式(Expression)
- 定义:执行后会产生一个值的代码片段。
- 特点:
- 没有分号结尾(或说分号会将表达式转为语句)。
- 可作为其他表达式的一部分(如
a + (b * c)
中的b * c
)。
- 示例:
5 + 3 // 表达式,返回8 "hello".len() // 表达式,返回5 if x > 0 { 1 } else { -1 } // 表达式,返回1或-1
2. 语句(Statement)
- 定义:执行某种操作但不产生值(或说返回
()
,单元类型)的代码片段。 - 特点:
- 通常以分号结尾。
- 包括变量声明(
let
)、赋值、函数调用(若忽略返回值)等。
- 示例:
let x = 5; // 变量声明语句,返回() x = 10; // 赋值语句,返回() println!("hi"); // 函数调用语句,返回()
3. 函数体的本质
Rust函数体本质上是一个表达式块(block expression),由一系列语句和一个最终表达式组成。函数的返回值就是这个最终表达式的结果(若省略return
)。
示例:
fn calculate() -> i32 {let a = 2; // 语句let b = 3; // 语句a * b // 最终表达式,作为函数返回值(无分号)
}println!("{}", calculate()); // 输出:6
函数体中,语句用于执行操作(如变量初始化),最终表达式决定返回值,这体现了Rust“表达式导向”的设计理念。
16. 如何定义一个没有返回值的函数?(提示:()
单元类型)
在Rust中,没有返回值的函数默认返回单元类型()
,定义方式有以下两种:
1. 省略返回值类型声明
- 函数签名中不写
-> 类型
,编译器默认其返回()
。
2. 显式声明返回()
- 函数签名中用
-> ()
明确指定返回单元类型,常用于强调函数无实际返回值。
单元类型()
:
- 是一个特殊类型,仅包含一个值
()
,表示“无有意义的值”。 - 类似于其他语言中的
void
,但()
是一个实际的类型和值(可存储或传递)。
示例:
// 省略返回值类型,默认返回()
fn greet() {println!("Hello!");
}// 显式声明返回()
fn log(message: &str) -> () {println!("[LOG]: {}", message);
}let result1 = greet();
let result2 = log("test");
println!("{:?}, {:?}", result1, result2); // 输出:(), ()
与void
的区别:
- C/C++中的
void
表示“无类型”,不能声明void
类型的变量。 - Rust的
()
是实际类型,可声明变量(如let x: () = ();
),更符合语言的类型一致性。
17. 函数可以嵌套定义吗?Rust的作用域规则是什么?
1. 函数嵌套定义
Rust不支持函数嵌套定义(即不能在一个函数内部定义另一个函数)。但可以通过闭包(Closure) 实现类似“嵌套函数”的功能(闭包是匿名函数,可在函数内部定义)。
示例:用闭包替代嵌套函数
fn outer_function() {// 闭包(匿名函数),类似嵌套函数let inner_closure = |x: i32| x * 2;let result = inner_closure(3);println!("{}", result); // 输出:6
}outer_function();
2. 作用域规则
Rust的作用域(Scope)是变量有效存在的代码范围,遵循以下规则:
- 块级作用域:由
{}
分隔的区域(如函数体、if
分支、循环体)都是作用域。 - 变量可见性:变量在其声明的作用域内可见,在作用域外不可访问。
- 嵌套作用域:内部作用域可访问外部作用域的变量(外层变量对内层可见),反之不行。
示例:
fn scope_demo() {let a = 10; // 外部作用域变量{let b = 20; // 内部作用域变量println!("a: {}, b: {}", a, b); // 正确:内部可访问外部}// println!("b: {}", b); // 错误:外部不可访问内部变量
}scope_demo(); // 输出:a: 10, b: 20
作用域规则确保了变量的生命周期可控,减少了命名冲突和意外修改的风险,是Rust内存安全的基础之一。
18. 举例说明函数参数的模式匹配(如解构元组、结构体)。
Rust允许在函数参数中直接使用模式匹配,简化对复杂类型(如元组、结构体)的解构操作,无需在函数体内手动拆分。
1. 解构元组参数
直接在参数列表中指定元组的结构,提取内部元素。
示例:
// 解构元组参数
fn print_tuple((x, y): (i32, &str)) {println!("x: {}, y: {}", x, y);
}let my_tuple = (42, "hello");
print_tuple(my_tuple); // 输出:x: 42, y: hello
2. 解构结构体参数
通过结构体字段名或位置(元组结构体)在参数中提取字段值。
示例:
// 普通结构体
struct Point {x: i32,y: i32,
}// 解构结构体参数(按字段名)
fn print_point(Point { x, y }: Point) {println!("Point: ({}, {})", x, y);
}// 元组结构体
struct Color(i32, i32, i32);// 解构元组结构体参数(按位置)
fn print_color(Color(r, g, b): Color) {println!("Color: RGB({}, {}, {})", r, g, b);
}print_point(Point { x: 10, y: 20 }); // 输出:Point: (10, 20)
print_color(Color(255, 0, 0)); // 输出:Color: RGB(255, 0, 0)
3. 解构枚举参数
匹配枚举的特定变体并提取关联数据。
示例:
enum Message {Quit,Move { x: i32, y: i32 },Write(String),
}// 解构枚举参数
fn process_message(msg: Message) {match msg {Message::Quit => println!("Quit"),Message::Move { x, y } => println!("Move to ({}, {})", x, y),Message::Write(s) => println!("Write: {}", s),}
}process_message(Message::Move { x: 5, y: 3 }); // 输出:Move to (5, 3)
process_message(Message::Write("hi".to_string())); // 输出:Write: hi
优势:函数参数模式匹配减少了手动解构的代码,使逻辑更清晰,同时利用了Rust模式匹配的穷尽性检查(如枚举匹配需覆盖所有变体)。
二、120道Rust面试题目录列表
文章序号 | Rust面试题120道 |
---|---|
1 | Rust面试题及详细答案120道(01-10) |
2 | Rust面试题及详细答案120道(11-18) |
3 | Rust面试题及详细答案120道(19-26) |
4 | Rust面试题及详细答案120道(27-32) |
5 | Rust面试题及详细答案120道(33-41) |
6 | Rust面试题及详细答案120道(42-50) |
7 | Rust面试题及详细答案120道(51-57) |
8 | Rust面试题及详细答案120道(58-65) |
9 | Rust面试题及详细答案120道(66-71) |
10 | Rust面试题及详细答案120道(72-80) |
11 | Rust面试题及详细答案120道(81-89) |
12 | Rust面试题及详细答案120道(90-98) |
13 | Rust面试题及详细答案120道(99-105) |
14 | Rust面试题及详细答案120道(106-114) |
15 | Rust面试题及详细答案120道(115-120) |