Rust “与”的区别是什么;mut retval`和'retval as*const T as*mut T T`?

Rust “与”的区别是什么;mut retval`和'retval as*const T as*mut T T`?,rust,Rust,我很难理解为什么以下代码有两种不同的行为: pub fn get(&self, idx: usize) -> &T { let arr = unsafe { core::slice::from_raw_parts(self.elements, self.count) }; &arr[idx] } 当我打电话时: unsafe { ptr::drop_in_place(self.get(i) as *const T as *mut T) }; 它可

我很难理解为什么以下代码有两种不同的行为:

pub fn get(&self, idx: usize) -> &T {
    let arr = unsafe { core::slice::from_raw_parts(self.elements, self.count) };
    &arr[idx]
}
当我打电话时:

unsafe { ptr::drop_in_place(self.get(i) as *const T as *mut T) };
它可以工作,并且将值放置到位,但是将强制转换更改为
&mut
不会:

unsafe { ptr::drop_in_place(&mut self.get(i)) };
我希望编译器会产生错误,因为
T
不支持克隆/复制,但事实并非如此。原因是什么

最简单的例子:

use core::*;

pub struct Vec<T> {
    elements: *mut T,
    count: usize,
    capacity: usize,
}

pub fn alloc_array<T>(count: usize) -> *mut T {
    let size = mem::size_of::<T>() * count;
    let addr = unsafe { libc::memalign(mem::size_of::<usize>(), size) as *mut T };
    unsafe { libc::memset(addr as *mut libc::c_void, 0, size) };
    addr
}

pub fn free_array<T>(arr: *mut T) {
    unsafe { libc::free(arr as *mut libc::c_void) };
}

impl<T> Vec<T> {
    pub fn new() -> Self {
        Self {
            elements: ptr::null_mut(),
            count: 0,
            capacity: 0,
        }
    }

    pub fn len(&self) -> usize {
        self.count
    }

    pub fn pushBack(&mut self, t: T) {
        if self.count >= self.capacity {
            let newSize = if self.capacity == 0 {
                16
            } else {
                self.capacity * 2
            };
            let old = self.elements;
            self.elements = alloc_array(newSize);
            self.capacity = newSize;

            let oldArr = unsafe { core::slice::from_raw_parts_mut(old, self.count) };
            let newArr = unsafe { core::slice::from_raw_parts_mut(self.elements, self.count + 1) };

            for i in 0..self.count {
                let v = unsafe { ptr::read(&oldArr[i] as *const _) };
                newArr[i] = v;
            }
        }
        let arr = unsafe { core::slice::from_raw_parts_mut(self.elements, self.count + 1) };

        arr[self.count] = t;
        self.count += 1
    }

    pub fn pop(&mut self) -> Option<T> {
        if self.count == 0 {
            None
        } else {
            self.count -= 1;
            Some(unsafe { ptr::read(self.get(self.count) as *const _) })
        }
    }

    #[inline]
    pub fn get(&self, idx: usize) -> &T {
        let arr = unsafe { core::slice::from_raw_parts(self.elements, self.count) };
        &arr[idx]
    }
}

impl<T> Drop for Vec<T> {
    fn drop(&mut self) {
        println!("Dropped");
        for i in 0..self.count {
            //unsafe { ptr::drop_in_place(self.get(i) as *const T as *mut T) };   // Works
            unsafe { ptr::drop_in_place(&mut self.get(i)) }; // Doesn't Works
        }
        if self.capacity != 0 {
            free_array(self.elements);
        }
    }
}

fn main() {
    let mut v = Vec::<Vec<i32>>::new();
    for i in 0..10 {
        let mut vj = Vec::<i32>::new();
        for j in 0..10 {
            vj.pushBack(j);
        }
        v.pushBack(vj);
    }
}
使用核心::*;
发布结构向量{
要素:*mut T,
计数:使用,
容量:usize,
}
pub fn alloc_数组(计数:usize)->*mut T T{
设size=mem::size_of::()*计数;
让addr=unsafe{libc::memalign(mem::size_of::(),size)作为*mut T};
不安全的{libc::memset(addr as*mut libc::c_void,0,size)};
地址
}
pub fn free_数组(arr:*mut T T){
不安全的{libc::free(arr as*mut libc::c_void)};
}
impl-Vec{
pub fn new()->Self{
自我{
元素:ptr::null_mut(),
计数:0,
容量:0,
}
}
pub fn len(&self)->使用{
自我计数
}
发布fn推送(和多个自身,t:t){
如果self.count>=self.capacity{
如果self.capacity==0,则让newSize=0{
16
}否则{
自我能力*2
};
让旧=自我元素;
self.elements=alloc_数组(newSize);
self.capacity=newSize;
设oldArr=unsafe{core::slice::from_raw_parts_mut(old,self.count)};
设newArr=unsafe{core::slice::from_raw_parts_mut(self.elements,self.count+1)};
因为我在0..self.count{
设v=unsafe{ptr::read(&oldArr[i]as*const};
newArr[i]=v;
}
}
设arr=unsafe{core::slice::from_raw_parts_mut(self.elements,self.count+1)};
arr[self.count]=t;
self.count+=1
}
pub fn pop(&mut self)->选项{
如果self.count==0{
没有一个
}否则{
self.count-=1;
一些(不安全的{ptr::read(self.get(self.count)as*const})
}
}
#[内联]
发布fn获取(&self,idx:usize)->&T{
设arr=unsafe{core::slice::from_raw_parts(self.elements,self.count)};
&arr[idx]
}
}
Vec的impl Drop{
fn下降(&mut自我){
println!(“删除”);
因为我在0..self.count{
//不安全的{ptr::drop_in_place(self.get(i)as*const T as*mut T T)};//有效
不安全的{ptr::drop_in_place(&mut self.get(i))};//不起作用
}
如果自容量!=0{
自由_数组(self.elements);
}
}
}
fn main(){
让mut v=Vec:::new();
因为我在0..10{
让mut vj=Vec:::new();
对于0..10中的j{
vj.回推(j);
}
v、 推回(vj);
}
}
瓦尔格林:

已删除
下降
下降
下降
下降
下降
下降
下降
下降
下降
下降
==6887== 
==6887==堆摘要:
==6887==在出口处使用:10个块中有640个字节
==6887==总堆使用率:30个alloc,20个free,分配4433个字节
==6887== 
==6887==搜索指向10个未释放块的指针
==6887==已检查107320字节
==6887== 
==6887==10个块中的640字节肯定会在丢失记录1(共1个)中丢失
==6887==at 0x4C320A6:memalign(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
==6887==by 0x10CB3F:minimal_test::alloc_数组(main.rs:11)
==6887==0x10cdc:minimal_test::Vec::pushBack(main.rs:35)
==6887==by 0x10E1BB:minimal_test::main(main.rs:85)
==6887==by 0x10C2DF:std::rt::lang_start:{{closure}}(rt.rs:67)
==6887==0x1165B2:{{closure}}(rt.rs:52)
==6887==by 0x1165B2:std::panicking::try::do_call(panicking.rs:305)
==6887==0x117D16:uu生锈u可能u陷入恐慌(lib.rs:86)
==6887==0x116F3F:try(惊慌失措。rs:281)
==6887==0x116F3F:catch_unwind(panic.rs:394)
==6887==0x116F3F:std::rt::lang\u start\u internal(rt.rs:51)
==6887==0x10C2B8:std::rt::lang_start(rt.rs:67)
==6887==0x10E259:main(在最小测试/目标/调试/最小测试中)
==6887== 
==6887==泄漏汇总:
==6887==肯定丢失:10个块中有640个字节
==6887==间接丢失:0个块中有0个字节
==6887==可能丢失:0个块中有0个字节
==6887==仍然可访问:0个块中有0个字节
==6887==抑制:0个块中有0个字节
==6887== 
==6887==错误摘要:来自1个上下文的1个错误(已抑制:来自0的0)
==6887==错误摘要:来自1个上下文的1个错误(已抑制:来自0的0)

请密切注意类型

pub fn get(&self, idx: usize) -> &T {
self.get(i)
具有类型
&T
。因此
&mut-self.get(i)
具有类型
&mut&T
。调用
drop\u in_place
将强制
&mut&T
*mut&T
并删除
&T
,这(因为共享引用不实现
drop
)不会产生任何效果

self.get(i)as*const\us*mut
&T
强制转换为
*const T
,然后转换为
*mut
调用
drop\u in_place
将在调用
时调用未定义的行为:drop
,它接受
&mut T这是错误的

不能通过共享引用对值进行变异(包括删除)。通过未加工的指针进行转换是不可能的。看


包含关于从头开始实施
Vec
的部分;我建议你读一读。

你是如何检查
ptr::drop\u in\u place
调用“工作”的?多一些代码(和a)就好了。使用valgrind并添加了一个最小的示例。
不起作用
是模糊的。它会导致编译错误吗?运行时错误?错误描述是什么<代码>我期望编译器会产生
代码也会产生,但您期望它不会,这就是“不工作”的原因<代码>640字节(10字节)