作者回复: 非常棒!
作者回复: 对!首先 () 的确不占内存。然后在文中我也提到,Rust 编译器会做一些优化: > Rust 是这么处理的,我们知道,引用类型的第一个域是个指针,而指针是不可能等于 0 的,但是我们可以复用这个指针:当其为 0 时,表示 None,否则是 Some。 对于 Result<String, ()> 也是如此,String 第一个域是指针,而指针不能为空,所以当它为空的时候,正好可以表述 Err(())。
作者回复: 1. 你引用的文字写的很清楚:which generally means that the data's memory address is a multiple of the *data size*。你想想一个 struct A {a: u8},它的 data size 是多少?如果要把它 align 在 64bit 上,那所有的 network buffer (相当于 Vec<u8>)都完蛋了,需要膨胀 8 倍。 这里有段代码,你可以看看,思考一下每个打印地址都如何对齐,然后运行感受一下: ```rust #[derive(Default)] struct Align1 { a: u8, b: usize, c: u32 } #[derive(Default)] struct Align2 { a: u8, } fn main() { let s1 = "a"; let s2 = "aaaa"; let s3 = "hello"; let a = Align1::default(); let b = Align2::default(); println!("{:p}", s1); println!("{:p}", s2); println!("{:p}", s3); println!("Align1.a: {:p}", &a.a); println!("Align1.b: {:p}", &a.b); println!("Align1.c: {:p}", &a.c); println!("Align2.a: {:p}", &b.a); } ``` playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9ab8c85b7065fb0374b046548517821f 2. c 对齐是 1,b 对齐是 2,所以 s2 是 2。注意 align 是对齐,不是长度,切记。就像 [u8; 1024] 长度是 1024,对齐依旧是 1。 3. Rust 目前不对外提供稳定的 ABI。所以如果要想以二进制形式分发,需要提供 C ABI 的接口。比如 struct 需要使用 #[repr(c)],很多标准库的数据结构需要使用对应的 C 结构(如 String)。所有的泛型函数,trait 方法,struct 方法,都需要对应的 C 函数封装。
作者回复: Result<T, E> 需要提供一个 E 类型代表错误,而在 show_size! 宏中,我们只传入了 T 的类型,所以这里就随便把 E 写死成 std::io::Error 了。std::io::Error 是 16 个字节,所以 Result<T, E>,如果不能优化的话,要么是 T + 8 个字节(T > 16),要么是 24 个字节(16 + 8)。
作者回复: feature 用作条件编译,你可以根据需要选择使用库的某些 feature。它的好处是可以让编译出的二进制比较灵活,根据需要装入不同的功能。在 docs.rs 下的某个库的文档中,你可以看到它都有哪些 feature。 定义 feature,你可以看 cargo book:https://doc.rust-lang.org/cargo/reference/features.html。下面是一个简单的例子: 在 cargo.toml 中,可以定义: [features] filter = ["futures-util"] // 定义 filter feature,它有额外对 futures-util 的依赖。 [dependencies] futures-util = { version = "0.3", optional = true } // 这个 dep 声明成 optional 在 lib.rs 中: #[cfg(feature = "filter")] pub mod filter_all; // 只有编译 feature filter 时,才引入 mod feature_all 编译
作者回复: 正确!
作者回复: A 不需要显示实现 Drop。文中已经说过编译器会依次为数据结构的每个字段调用其 Drop(如果有 Drop 实现的话)。你可以认为当一个需要 drop 的值 a 退出作用域时,都会进行类似 drop(a) 的操作。 你可以看这个代码:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018。把 playground 切到 Show MIR 再运行看插入的 drop。
编辑回复: 啊确实是,已经修改过来啦,感谢反馈~
作者回复: 对!
作者回复: 对