Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

结构体表达式

Syntax
StructExpression
    PathInExpression { ( StructExprFields | StructBase )? }

StructExprFields
    StructExprField ( , StructExprField )* ( , StructBase | ,? )

StructExprField
    OuterAttribute*
    (
        IDENTIFIER
      | ( IDENTIFIER | TUPLE_INDEX ) : Expression
    )

StructBase.. Expression

一个 结构体表达式 创建一个结构体、枚举或联合体值。 它由指向 结构体枚举变体联合体 项 的路径,以及随后该 项 的字段值组成。

以下是结构体表达式的示例:

#![allow(unused)]
fn main() {
struct Point { x: f64, y: f64 }
struct NothingInMe { }
mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } }
enum Enum { Variant {} }
Point {x: 10.0, y: 20.0};
NothingInMe {};
let u = game::User {name: "Joe", age: 35, score: 100_000};
Enum::Variant {};
}

注意

元组结构体和元组枚举变体通常使用引用 值命名空间中的构造函数调用表达式 来实例化。这些不同于使用花括号引用类型命名空间中构造函数的结构体表达式。

#![allow(unused)]
fn main() {
struct Position(i32, i32, i32);
Position(0, 0, 0);  // 创建元组结构体的典型方式。
let c = Position;  // `c` 是一个接受 3 个参数的函数。
let pos = c(8, 6, 7);  // 创建一个 `Position` 值。

enum Version { Triple(i32, i32, i32) };
Version::Triple(0, 0, 0);
let f = Version::Triple;
let ver = f(8, 6, 7);
}

调用路径的最后一段不能引用类型别名:

#![allow(unused)]
fn main() {
trait Tr { type T; }
impl<T> Tr for T { type T = T; }

struct Tuple();
enum Enum { Tuple() }

// <Unit as Tr>::T(); // 导致错误 —— `::T` 是一个类型,而不是一个值
<Enum as Tr>::T::Tuple(); // 确定
}

单元结构体和单元枚举变体通常使用引用 值命名空间中的常量路径表达式 来实例化。

#![allow(unused)]
fn main() {
struct Gamma;
// Gamma 单元值,引用值命名空间中的常量。
let a = Gamma;
// 与 `a` 完全相同的值,但是使用引用类型命名空间的结构体表达式构造的。
let b = Gamma {};

enum ColorSpace { Oklch }
let c = ColorSpace::Oklch;
let d = ColorSpace::Oklch {};
}

带字段的结构体表达式

带有花括号包围字段的结构体表达式允许你以任意顺序指定每个单独字段的值。 字段名与其值之间用冒号分隔。

联合体 类型的值只能使用此语法创建,并且必须指定恰好一个字段。

函数式更新语法

构造结构体类型值的结构体表达式可以以语法 .. 后跟一个表达式结束,以表示函数式更新。

.. 之后的表达式(基准)必须具有与正在形成的新结构体类型相同的结构体类型。

整个表达式使用指定的字段的给定值,并从基准表达式中移动 (move) 或复制 (copy) 剩余的字段。

与所有结构体表达式一样,结构体的所有字段必须是 可见 的,即使是那些没有明确命名的字段。

#![allow(unused)]
fn main() {
struct Point3d { x: i32, y: i32, z: i32 }
let mut base = Point3d {x: 1, y: 2, z: 3};
let y_ref = &mut base.y;
Point3d {y: 0, z: 10, .. base}; // 确定,仅访问了 base.x
drop(y_ref);
}

结构体表达式不能直接用于 loopif 表达式的头部,也不能用于 if letmatch 表达式的 审查对象。 然而,如果结构体表达式位于另一个表达式之内(例如在 括号 内),则可以用于这些情况。

字段名可以是十进制整数值,用于指定构造元组结构体的索引。 这可以与基准结构体一起使用,以填充未指定的其余索引:

#![allow(unused)]
fn main() {
struct Color(u8, u8, u8);
let c1 = Color(0, 0, 0);  // 创建元组结构体的典型方式。
let c2 = Color{0: 255, 1: 127, 2: 0};  // 按索引指定字段。
let c3 = Color{1: 0, ..c2};  // 使用基准结构体填充所有其他字段。
}

结构体字段初始化简写

当初始化具有命名(但不是编号)字段的数据结构(结构体、枚举、联合体)时,允许将 fieldname 写为 fieldname: fieldname 的简写。 这允许一种更紧凑、重复更少的语法。 例如:

#![allow(unused)]
fn main() {
struct Point3d { x: i32, y: i32, z: i32 }
let x = 0;
let y_value = 0;
let z = 0;
Point3d { x: x, y: y_value, z: z };
Point3d { x, y: y_value, z };
}