结构体和枚举之间的区别

Muh*_*qui 3 rust

我对《Rust Book》中的这一说法感到困惑:

\n
\n

使用枚举而不是结构还有另一个优点:每个变体可以具有不同类型和数量的关联数据。版本四类型 IP 地址始终有四个数字组成部分,其值介于 0 到 255 之间。如果我们想将 V4 地址存储为四个u8值,但仍将 V6 地址表示为一个String值,我们将\xe2\x80\x99t 无法与一个 struct。枚举可以轻松处理这种情况:

\n
#![allow(unused_variables)]\nfn main() {\n    enum IpAddr {\n        V4(u8, u8, u8, u8),\n        V6(String),\n    }\n\n    let home = IpAddr::V4(127, 0, 0, 1);\n\n    let loopback = IpAddr::V6(String::from("::1"));\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

但是,当我尝试使用结构将 V4 地址存储为四个u8值但仍将 V6 地址表示为一个String值时,它也执行相同的操作,没有任何错误。

\n
#[derive(Debug)]\nstruct IpAddr {\n    V4:(u8, u8, u8, u8),\n    V6:String,\n}\n\nfn main () {\n    let home = IpAddr {\n        V4: (127, 1, 1, 1), \n        V6: String::from("Hello"),\n    };\n    println!("{:#?}", home);      \n}\n
Run Code Online (Sandbox Code Playgroud)\n

Sve*_*rev 5

这是不一样的。所有枚举元素都具有完全相同的大小!枚举元素的大小是最大变体的大小加上变体标识符。

对于结构体来说,情况有点不同。如果我们忽略填充,结构体的大小就是其成员大小的总和。有了填充,它会多一点:

fn main() {
    let size = std::mem::size_of::<TheEnum>();
    println!("Enum: {}", size * 8);

    let size = std::mem::size_of::<TheStruct>();
    println!("Struct: {}", size * 8);
}

struct TheStruct {
    a: u64,
    b: u8,
    c: u64
}

enum TheEnum {
    A(u64),
    B(u8),
    C(u64)
}
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到区别:

  • 枚举:128;64 表示最大变体,64 表示变体标识符。

  • 结构:192;与 64 位对齐,因此我们有 54 位填充

另一个区别在于使用枚举和结构的方式。在枚举中,您只需初始化其中一种变体。根据您的情况 - IPv4 或 IPv6。对于示例中的结构,您必须提供 V4 和 v6 地址。您不能仅提供 V4 或仅提供 V6。