// 什么是Sized?
// Sized是Rust再编译阶段检查对象操作的一个基本依据,
// Rust只允许操作已知大小的对象, 未知大小的对象只能操作它的指针(&).
fn sized_correct() {
#[derive(Debug)]
struct Water<T>(T); // 等同于 struct Status<T: Sized>(T);
#[derive(Debug)]
struct Cup(Water<i32>);
let water = Water(10);
let cup = Cup(water);
println!("{:?}", cup); // output: Cup(Water(10))
}
// 问题代码, 需要注释掉才能运行.
//fn sized_error() {
// #[derive(Debug)]
// struct Water<T>(T); // 等同于 struct Status<T: Sized>(T);
//
// #[derive(Debug)]
// struct Cup(Water<[i32]>); // 由于[i32] 是一个队列, 因此它是未知大小
//}
fn use_unsized_to_fix_sized_error() {
#[derive(Debug)]
#[allow(dead_code)]
struct Bar<T: ?Sized>(T);
#[derive(Debug)]
#[allow(dead_code)]
struct BarUse<'a>(Bar<&'a [i32]>);
}
fn thinking() {
#[derive(Debug)]
#[allow(dead_code)]
struct Bar<T: ?Sized>(T);
#[derive(Debug)]
#[allow(dead_code)]
struct BarUse<'a>(Bar<&'a [i32]>);
// 备注: 虽然这里可以定义Bar<[i32]> ,
// 但是实际上实现起来不能直接写slice, 因为编译器不允许未知大小的东西编译通过,
// 解决办法是改成&[i32]
let s = [1,2,3,4];
let bar = Bar(&s[0..2]);
let bu = BarUse(bar);
println!("{:?}", bu);
// 写成这样能运行的原因是, &s[0..2]是一个引用, 引用就是一个指针, 指针是固定大小的.
// 如果指针是固定大小的, 那么上面定义的?Sized对于这个例子来说就没有意义了.
// 这个问题我现在的水平还无法解决, 等以后水平不断深入在来解决把, 先留个TODO
// TODO: FIXME.
}
fn main() {
sized_correct();
// sized_error();
use_unsized_to_fix_sized_error();
thinking();
}
网友评论