Rust中实现C++闭包捕获this的等效规范写法探讨
Rust 里模拟 C++ 闭包捕获
this 的规范写法 核心逻辑
Rust 没有 C++ 那种直接捕获 this 的语法,但可以通过自引用结构体结合 Pin 实现安全的自引用初始化;如果共享状态是原子类型,完全不用额外加锁,靠原子操作本身的线程安全性就能搞定。
针对原子类型场景的实现
假设你的 Looper 结构体用原子类型(比如 AtomicBool)存储共享状态,两种靠谱写法如下:
1. 自引用结构体 + Pin(适合需要直接操作自身的场景)
用 Pin<Box<...>> 把结构体钉死在内存里,避免自引用指针失效:
use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; struct Looper { running: AtomicBool, callback: Option<Pin<Box<dyn FnMut() + 'static>>>, } impl Looper { fn new() -> Pin<Box<Self>> { // 先创建不带回调的实例,用Pin固定内存位置 let mut looper = Box::pin(Looper { running: AtomicBool::new(true), callback: None, }); // 用unsafe获取可变引用,只要后续不移动Pin包裹的结构体就安全 let looper_ref = unsafe { Pin::get_mut_unchecked(&mut looper) }; // 初始化回调,直接捕获自身的可变引用 looper_ref.callback = Some(Box::pin(move || { if looper_ref.running.load(Ordering::Relaxed) { println!("Looping..."); looper_ref.running.store(false, Ordering::Relaxed); } })); looper } fn run(&mut self) { if let Some(callback) = &mut self.callback { callback.as_mut()(); } } }
2. 抽离共享状态(完全无unsafe,更简洁)
把原子类型的状态单独拎出来,让闭包捕获它的克隆引用(原子类型的克隆是共享同一内存,相当于间接访问自身状态):
use std::sync::atomic::{AtomicBool, Ordering}; struct Looper { running: AtomicBool, callback: Option<Box<dyn FnMut() + 'static>>, } impl Looper { fn new() -> Self { let running = AtomicBool::new(true); // 克隆原子变量,本质是共享同一底层内存 let running_clone = running.clone(); let callback = Some(Box::new(move || { if running_clone.load(Ordering::Relaxed) { println!("Looping..."); running_clone.store(false, Ordering::Relaxed); } })); Looper { running, callback } } fn run(&mut self) { if let Some(callback) = &mut self.callback { callback(); } } }
为什么不用 Arc<Mutex>?
原子类型本身已经保证了线程安全和内存可见性,Mutex 完全是多余的;如果不需要跨线程共享,连 Arc 都不用。只有当共享状态是非原子的复杂类型,且要跨线程共享时,才需要 Arc<Mutex> 那套东西。
内容的提问来源于stack exchange,提问作者LittleBoxOfSunshine
相关产品推荐
相关产品推荐

