为什么Drop
的方法有签名Aggregation : CONCAT, COUNT, SUM, MAX, MIN, AVG, MEDIAN, MODE, INDEXOF_MAX, INDEXOF_MIN
Comparison : =,>,<, LIKE/NOT LIKE, NULL/NOT NULL, IN/NOT IN, Dates comparison
Boolean operators : AND,OR,NOT,XOR
而不是Band/Range JOIN, Self JOIN
Views (Temporary files?), Difference/Except, Division
Sub-queries/Nested queries
Contingency tables
?这使得难以将值移出字段,例如self.join_handle.join()
或fn drop(&mut self)
(错误:无法移出定义fn drop(self)
特征的std::mem::drop(self.file)
类型。
答案 0 :(得分:14)
让我们看一下std::mem::drop
的实施方式:
pub fn drop<T>(_x: T) { }
这是对的:这是一个空功能!那是因为它利用移动语义来获得其参数的所有权。如果T
实现Drop
,编译器会自动在函数末尾插入对Drop::drop(_x)
的调用。这会发生在按值接收的所有参数上(实际上,所有参数,但删除引用不会丢弃引用)。
现在考虑如果Drop::drop
通过值获取其参数会发生什么:编译器会尝试在Drop::drop
内的参数上调用Drop::drop
- 这会导致堆栈溢出!当然,您可以在参数上调用mem::drop
,该参数也会尝试以递归方式调用Drop::drop
。
答案 1 :(得分:6)
实际上,Drop::drop
不必拥有该值的所有权。
在Rust中,所有权在语言级别自动处理,因此编译确保正确实现所有权语义;因此,当Foo { a: int, b: String }
超出范围时,编译器将通过自动删除其内部字段来删除Foo
。
因此Drop::drop
无需删除字段!
实际上,在Drop::drop
上调用 Foo
之后的,编译器本身会mem::drop
不同的字段(也可能会调用Drop::drop
那些定义它的字段,例如b: String
这里。)
Drop::drop
做什么呢?
它用于在编译器执行的操作之上实现额外逻辑;以你的JoinHandle
为例:
#[stable(feature = "rust1", since = "1.0.0")]
#[unsafe_destructor]
impl<T> Drop for JoinHandle<T> {
fn drop(&mut self) {
if !self.0.joined {
unsafe { imp::detach(self.0.native) }
}
}
}
此处,Drop::drop
用于分离线程,例如。
在Vec::vec
:
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
// This is (and should always remain) a no-op if the fields are
// zeroed (when moving out, because of #[unsafe_no_drop_flag]).
if self.cap != 0 && self.cap != mem::POST_DROP_USIZE {
unsafe {
for x in &*self {
ptr::read(x);
}
dealloc(*self.ptr, self.cap)
}
}
}
}
这里,由于原始内存以对编译器不透明的方式进行操作,因此该实现负责:
答案 2 :(得分:1)
尽管上面有很好的答案,但我仍然需要澄清。这就是我得到的......
pub trait Drop {
pub fn drop(&mut self);
}
需要 mutable reference
而不是 move
,因为 drop
函数不是为了释放内存而只是在发布之前执行准备工作。因此,drop
函数的更好名称可能是 prepare_to_drop
。
实际的内存释放由std::mem
模块中的一个函数执行,定义如下:
pub fn drop<T>(_x: T) { }
正如预期的那样,它显然使用了编译器生命周期管理语义。如果我们假设编译器隐式地为所有没有实现自己的类型派生了一个空的 Drop
特征,那么这个特定函数的一个更具启发性的编码揭示了编译器的体操......
pub fn drop<T: Drop>(x: T) { //this is a bare function (no Self)
x.drop();
}
最后,Drop trait 需要 mutable reference
, &mut T
而不是 shared reference
, &T
的原因是准备工作可能包括改变 {{ 1}},例如移出内容、在 T
上不允许的操作。