我有一个结构
struct Foo<'a> {
buf: [u8, ..64],
slice: &'a [u8]
}
Run Code Online (Sandbox Code Playgroud)
切片应该指向buf结构的字段.有没有办法构建这样的结构?就像是:
impl<'a> Foo<'a> {
fn new() -> Foo<'a> {
Foo {
buf: [0, ..64],
slice: ???? /* I don't know what to write here */
}
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试执行类似下面的操作,则借用检查器会(正确地)抱怨,因为切片的生命周期将比结构更短.
impl<'a> Foo<'a> {
fn new() -> Foo<'a> {
let buf = [0, ..64];
Foo {
buf: buf,
slice: buf.slice_from(0)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我意识到,对于这个简单的情况,我可以保留偏移量并手动调用切片函数:
struct Foo {
buf: [u8, ..64],
slice_from: uint,
slice_to: uint
}
Run Code Online (Sandbox Code Playgroud)
然而,这个问题只是对拥有数据的结构的更一般用例的简化,并且引用了相同的数据,我想知道在Rust中是否可以(以安全的方式).
不,你不能安全地做到这一点,因为一般来说这样的结构是不可移动的.假装它是可能的,你可以创建这样的结构:
let foo = Foo {
buf: [0, ..64],
slice: obtain_slice_somehow()
};
Run Code Online (Sandbox Code Playgroud)
该slice字段现在是一个buf字段,特别是它包含一个指向buf目前位于堆栈上的指针.现在放入foo一个盒子并从函数中返回:
return Box::new(foo);
Run Code Online (Sandbox Code Playgroud)
foovalue现在被移动到堆,函数退出,释放它的堆栈内存.但是,slice指针没有调整为指向堆,因为一般不可能这样做,所以它留下了悬空,违反了内存安全.