use std::marker;
use std::ops;
pub struct Shared<'r, T: 'r> {
data: *mut T,
_pd: marker::PhantomData<&'r T>,
}
impl<'r, T> Shared<'r, T> {
pub fn new(value: T) -> Shared<'r, T> {
let boxed = Box::new(value);
Shared {
data: Box::into_raw(boxed),
_pd: marker::PhantomData,
}
}
pub fn as_ref(&self) -> SharedRef<'r, T> {
SharedRef {
data: self.data,
_pd: marker::PhantomData,
}
}
}
impl<'r, T> ops::Deref for Shared<'r, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.data }
}
}
pub struct SharedRef<'r, T: 'r> {
data: *mut T,
_pd: marker::PhantomData<&'r T>,
}
impl<'r, T> ops::Deref for SharedRef<'r, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.data }
}
}
impl<'r, T> Drop for Shared<'r, T> {
fn drop(&mut self) {
unsafe {
Box::from_raw(self.data);
}
}
}
fn main() {
let s = Shared::new(42);
let s_ref = s.as_ref();
{
let s1 = s;
}
// lifetime should end here
println!("{}", *s_ref);
}
我想表达的是 Box
和 Arc
的混合。一个唯一拥有的指针,也能够给出引用。
问题是我希望能够移动 Shared
,即使当前有不可变的借用。在这种情况下它应该是合法的,因为它是堆分配的。
问题是我不知道如何表达。
fn main() {
let s = Shared::new(42);
let s_ref = s.as_ref();
{
let s1 = s;
}
// lifetime should end here
println!("{}", *s_ref);
}
在这里,我将 s
移动到一个生命周期比以前“短”的范围内。但是现在,在我将 s
移动到 s1
之后,应该不再可以访问 s_ref
了。所以我想说的是,如果生命周期没有变小,移动一个Shared
是可以的。
这可以用 Rust 表达吗?
最佳答案
Rust 允许您移出 Shared
的原因是你没有绑定(bind)返回的生命周期 SharedRef
对它:
pub fn as_ref(&self) -> SharedRef<'r, T> {
SharedRef {
data: self.data,
_pd: marker::PhantomData,
}
}
注释 &self
修复:
pub fn as_ref(&'r self) -> SharedRef<'r, T> { .. }
我目前的理解是,这里的主要区别在于这表示 SharedRef
的生命周期现在与 self
的借用 的生命周期匹配, 保持借用。事实上,它不必与 'r
中的生命周期( Shared
)相同。 ;它只为借用/归还而使用新的生命周期:
pub fn as_ref<'b>(&'b self) -> SharedRef<'b, T> { .. }
这也不允许移动。
至于问题的额外部分,只要是生命周期足够长的东西,您就可以允许移动,我认为答案是否定的。我知道阻止某物被移动的唯一方法就是借用它,这会阻止任何移动。
关于rust - 即使借用不可变的东西也有可能移动吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39056626/