在Rust中,如何释放全局静态的OnceCell的内部对象?
我有以下代码
use tokio::sync::OnceCell;
struct MyStruct {}
impl MyStruct {
pub fn new() -> anyhow::Result<Self> {
Ok(Self {})
}
}
impl Drop for MyStruct {
fn drop(&mut self) {
println!("---> auto drop .")
}
}
static HOLDER: OnceCell<MyStruct> = OnceCell::const_new();
async fn g2() -> &'static MyStruct {
HOLDER
.get_or_init(|| async { MyStruct::new().unwrap() })
.await
}
#[tokio::main]
async fn main() {
println!("Hello, world!");
// _ms will auto drop
let _ms = MyStruct {};
// the inner object, instance of `MyStruct` will not drop
let _ins = g2().await;
}
Cargo.toml
[dependencies]
anyhow = "1.0.102"
tokio = {version = "1.52.0", features = ["full"]}
正如注释所说,_ms 将会自动被丢弃,但 _ins 不会被丢弃。
我的问题是如何丢弃由 HOLDER 创建的 MyStruct 实例。
解决方案
原因是 HOLDER 是一个静态变量,静态变量是全局的,存在永远并且会 参见文档:
[items.static.lifetime] 静态项具有静态生命周期,超出Rust程序中的所有其他生命周期。静态项在程序结束时不会调用drop。
你在这里实现的范式被称为单例模式,其中 g2() 是单例访问器。Rust的单例在程序结束时不会被丢弃,它们只是不再存在。
我的问题是如何丢弃由HOLDER创建的MyStruct实例。
不要把它设为全局静态变量。把它声明在 main 中,并作为参数传递。避免全局静态变量有很多原因,这只是其中一个。
如果你只是想要以C 风格的编程,拥有一组函数及它们所操作的全局变量,那么将所有变量放到一个结构体中,并把函数移入该结构体 impl,并带一个 &self/&mut self 参数。然后在 main 函数中初始化该结构体,并调用该结构体的入口函数或类似的函数。这几乎会得到与仅使用全局函数相同的布局,但有一个好处:它们现在绑定到一个将被可靠丢弃的结构体上。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。