说明
rust 的变量,结构体,函数等概念和其他语言基本类似。
区别在于,变量有 不可变变量(immutable)和可变变量(mutable);
变量
rust是强类型语言,所有变量在使用之前需要先用 let 关键字定义;
fn main() {
let h: i32 = 10; // 定义一个32位有符号整型变量h,为不可变变量,初始值为10
println!("h={}", h);
// 修改不可变变量 h 会导致编译出错
// h = 20;
}
fn main() {
let mut m: u64 = 99; // 定义一个64位无符号整型变量 m ,mut代表可变变量,初始值为99
println!("before changing, m={}", m);
m = 100; // 修改 m 的值
println!("after changing, m={}", m);
}
fn main() {
let h: i32 = 10; // 定义一个32位有符号整型不可变变量 h ,值为10
println!("first h={}", h);
let h: i64 = 20; // 重新定义变量 h
println!("second h={}", h);
}
引用
rust 的引用和C++的引用类似,可以理解是变量的别名。
引用的规则:
- rust的引用分 “可变应用” 和 “不可变引用”
- 可变变量:可以有且只有1个“可变引用” 或者 多个“不可变引用”
- 不可变变量:可以有多个“不可变引用”,不能有可变引用
- 一个变量不能同时存在“可变引用”和“不可变引用”
- 一个变量如果存在可变引用,在可变引用的作用范围内,不可以使用原变量
从内存安全角度来看这些规则很好理解。
- 如果存在多个“可变引用”,就可能同时存在写操作的冲突
- 如果存在“可变引用” 和 “不可变引用”,写操作和读操作会有冲突
- 如果存在 多个 “不可变引用”,都是读操作,没有冲突
fn main() {
let v: i32 = 10;
let r1: &i32 = &v; // 不可变引用
let r2 = &v; // r1 和 r2都是 v 的不可变引用
println!("immutable v {}, r1 {}, r2 {}", v, r1, r2);
// r1
let mut v: i32 = 10; // 可变变量才能可变引用
let r1 = &mut v; // r1 是 v 的可变引用
// let r2 = &mut v; // 已经有一个可变引用r1,再创建一个可变引用 r2 会编译出错
// println!("mutable v {}", v); // 已经有一个可变引用 r1,不能再访问原变量 v
*r1 = 100; // 写操作,修改可变引用的变量值
println!("mutable reference r1 {}", r1); // 访问可变引用 r1
// rust会自动判断可变引用 r1 已经不再被使用
// 所以这里可以继续访问原变量
println!("mutable v {}", v);
}
函数
函数用 fn 关键字声明。
// 没有参数的函数
fn test0() {
println!("test0() without args");
}
// 有 1 个参数的函数
fn test1(h: i32) {
println!("test1() with one arg {}", h);
}
// 有多个参数的函数
fn test2(h1: i32, h2: i32, h3: i32) {
println!("test2() with args, h1 {}, h2 {}, h3 {}", h1, h2, h3);
}
// 有 1 个返回值的函数
fn test3() -> i32 {
let h: i32 = 33;
return h;
}
// 有多个返回值的函数
fn test4() -> (i32, i32, i32) {
return (41, 42, 43);
}
// 最后一条语句如果是 return 语句,可以省掉 return 关键字且行尾没有分号
fn test5() -> i32 {
let h: i32 = 33;
h
}
// 参数是引用的函数
fn test6(n: &i32) -> i32 {
*n // 解引用并返回
}
fn main() {
test0(); // 调用函数,无参数
test1(11); // 调用函数,1个参数
test2(21, 22, 34); // 调用函数,多个参数
let h = test3();
println!("test3() return {}", h);
let (h1, h2, h3) = test4();
println!("test4() return ({}, {}, {})", h1, h2, h3);
let h = test5();
println!("test5() return {}", h);
let n = 111;
let h = test6(&n);
println!("test6() return {}", h);
}
结构体
结构体用 struct 关键字声明,是用户自定义的数据类型。
// 声明结构体 Point
struct Point{
x: i32,
y: i32,
}
fn main() {
let point: Point = Point{x: 1, y: 2}; // 定义 Point 变量
println!("Point: x={}, y={}", point.x, point.y);
let point = Point{x: 3, y: 4}; // 可以省略变量类型,编译会自动推断出类型
println!("Point: x={}, y={}", point.x, point.y);
}
类型成员函数
// 声明结构体 Point
struct Point{
x: i32,
y: i32,
}
impl Point {
fn new(x0: i32, y0: i32) -> Self { // Self 是指当前类型 Point
Self{ x: x0, y: y0,} // 新建 Point 对象并返回
}
// self 类似 C++ 或 Java 的 this
fn get(&self) -> (i32, i32) {
return (self.x, self.y);
}
}
fn main() {
let point: Point = Point::new(1, 2);
println!("Point: x={}, y={}", point.x, point.y);
let (x, y) = point.get();
println!("point.get(): x={}, y={}", x, y);
}