|
|
|
@ -11,7 +11,7 @@
|
|
|
|
|
一个结构体有几部分组成:
|
|
|
|
|
- 通过关键字`struct`定义
|
|
|
|
|
- 一个清晰明确的结构体`名称`
|
|
|
|
|
- 数个具名的结构体`字段`
|
|
|
|
|
- 几个有名字的结构体`字段`
|
|
|
|
|
|
|
|
|
|
例如以下结构体定义了某网站的用户:
|
|
|
|
|
```rust
|
|
|
|
@ -22,7 +22,7 @@ struct User {
|
|
|
|
|
sign_in_count: u64,
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
该结构体名称是`User`,拥有4个具名的字段,且每个字段都有对应的类型声明,例如`username`代表了用户名,是一个可变的`String`类型。
|
|
|
|
|
该结构体名称是`User`,拥有4个字段,且每个字段都有对应的字段名及类型声明,例如`username`代表了用户名,是一个可变的`String`类型。
|
|
|
|
|
|
|
|
|
|
#### 创建结构体实例
|
|
|
|
|
为了使用上述结构体,我们需要创建`User`结构体的**实例**:
|
|
|
|
@ -50,7 +50,7 @@ struct User {
|
|
|
|
|
|
|
|
|
|
user1.email = String::from("anotheremail@example.com");
|
|
|
|
|
```
|
|
|
|
|
需要注意的是,必须要将整个结构体都声明为可变的,才能修改它,Rust不允许单独将某个字段标记为可变: `let mut user1 = User {...}`.
|
|
|
|
|
需要注意的是,必须要将整个结构体都声明为可变的,才能修改其中的字段,Rust不允许单独将某个字段标记为可变: `let mut user1 = User {...}`.
|
|
|
|
|
|
|
|
|
|
#### 简化结构体创建
|
|
|
|
|
下面的函数类似一个构建函数,返回了`User`结构体的实例:
|
|
|
|
@ -98,7 +98,7 @@ fn build_user(email: String, username: String) -> User {
|
|
|
|
|
```
|
|
|
|
|
因为`user2`仅仅在`email`上与`user1`不同,因此我们只需要对`email`进行赋值,剩下的通过结构体更新语法`..user1`即可完成。
|
|
|
|
|
|
|
|
|
|
`..`语法说明我们没有显示声明的字段全部从`user1`中自动获取。需要注意的是`..user1`必须在结构体的尾部使用。
|
|
|
|
|
`..`语法表明凡是我们没有显示声明的字段,全部从`user1`中自动获取。需要注意的是`..user1`必须在结构体的尾部使用。
|
|
|
|
|
|
|
|
|
|
> 结构体更新语法跟赋值语句`=`非常相像,因此在上面代码中,`user1`的部分字段所有权被转移到`user2`中:`username`字段发生了所有权转移,作为结果,`user1`无法再被使用。
|
|
|
|
|
>
|
|
|
|
@ -165,7 +165,7 @@ println!("{:?}", user1);
|
|
|
|
|
|
|
|
|
|
从图中可以清晰的看出`File`结构体两个字段`name`和`data`分别拥有底层两个`[u8]`数组的所有权(`String`类型的底层也是`[u8]`数组),通过`ptr`指针指向底层数组的内存地址,这里你可以把`ptr`指针理解为Rust中的引用类型。
|
|
|
|
|
|
|
|
|
|
该图片也侧面印证了:把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段.
|
|
|
|
|
该图片也侧面印证了:**把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段**.
|
|
|
|
|
|
|
|
|
|
## 元组结构体(Tuple Struct)
|
|
|
|
|
|
|
|
|
@ -198,7 +198,7 @@ impl SomeTrait for AlwaysEqual {
|
|
|
|
|
|
|
|
|
|
## 结构体数据的所有权
|
|
|
|
|
|
|
|
|
|
在之前的`User` 结构体的定义中,我们使用了自身拥有所有权的 `String` 类型而不是基于引用的`&str` 字符串切片类型。这是一个有意而为之的选择,因为我们想要这个结构体拥有它所有的数据,而不是从其它地方借用数据。
|
|
|
|
|
在之前的`User` 结构体的定义中,有一处细节:我们使用了自身拥有所有权的 `String` 类型而不是基于引用的`&str` 字符串切片类型。这是一个有意而为之的选择,因为我们想要这个结构体拥有它所有的数据,而不是从其它地方借用数据。
|
|
|
|
|
|
|
|
|
|
你也可以让`User`结构体从其它对象借用数据,不过这么做,就需要引入**生命周期**这个新概念(也是一个复杂的概念),简而言之,生命周期能确保结构体的作用范围要比它所借用的数据的作用范围要小。
|
|
|
|
|
|
|
|
|
|