AI Agent投资回报率的科学计算方法
2026/4/11 5:02:06
目标:帮助新手小白理解 Rust 的核心概念(所有权、借用、引用、生命周期、结构体、trait、智能指针等)并通过可运行的代码示例掌握实战要点。文档按主题分块,便于学习与查阅。💡
String、Vec等),源变量不再可用。示例:
fnmain(){lets1=String::from("hello");// s1 拥有堆上的数据lets2=s1;// move:s1 的所有权被移动到 s2// println!("{}", s1); // 错误:s1 已经被移动,不能再使用println!("{}",s2);}解释要点:
String),赋值会移动所有权而不是深拷贝。Copytrait,赋值会按位复制,不会移动所有权。Copy:按位复制(仅适合小的、固定大小、无需析构逻辑的类型,如i32、bool、char)。复制时不调用drop,不会使原变量失效。Clone:显式深拷贝(可能需要堆分配),需要调用clone()。可能有运行时成本。示例:
fnmain(){letx=5;// i32: Copylety=x;// x 仍然可用println!("x = {}, y = {}",x,y);lets1=String::from("hi");lets2=s1.clone();// 深拷贝println!("s1 = {}, s2 = {}",s1,s2);}建议:尽量避免不必要的clone(),优先通过引用借用数据。
&T)与可变借用(&mut T)。示例:
fnmain(){lets=String::from("hello");letlen=calculate_length(&s);// 借用 &s,不取得所有权println!("len = {}",len);}fncalculate_length(s:&String)->usize{s.len()}解释:
&s是不可变借用,函数不能修改s。规则:
可变借用示例:
fnmain(){letmuts=String::from("hello");change(&muts);println!("{}",s);// "hello, world"}fnchange(s:&mutString){s.push_str(", world");}错误示例(不可变 & 可变同事存在)
fnmain(){letmuts=String::from("hello");letr1=&s;// 不可变借用letr2=&s;// 另一个不可变借用letr3=&muts;// 错误:同时存在可变借用和不可变借用}要点:限制借用范围,避免同时存在冲突借用。
'a)来帮助编译器验证引用不会变成悬垂引用。示例(错误):
// 错误:不能返回指向局部变量的引用fninvalid()->&String{lets=String::from("hello");&s// s 在函数结束时被销毁,返回引用悬垂}正确用法(返回传入引用的一部分):
fnlongest<'a>(x:&'astr,y:&'astr)->&'astr{ifx.len()>y.len(){x}else{y}}结构体持有引用的例子:
structImportantExcerpt<'a>{part:&'astr,}fnmain(){letnovel=String::from("Call me Ishmael. Some text...");letfirst_sentence=novel.split('.').next().expect("no sentence");leti=ImportantExcerpt{part:first_sentence};}要点:生命周期注解说明引用之间的关系,不影响程序运行时行为。
String:可变,堆分配,拥有所有权。&str:字符串切片,借用的数据视图(静态字符串或String的一部分)。切片示例:
fnmain(){lets=String::from("hello world");lethello=&s[0..5];// &str:借用 s 的一部分println!("{}",hello);}集合示例(Vec 移动):
fnmain(){letv=vec![1,2,3];letv2=v;// move// println!("{:?}", v); // 错误:v 被移动println!("{:?}",v2);}若需要共享数据,使用引用或Rc/Arc。
定义与方法示例:
#[derive(Debug, PartialEq)]structRectangle{width:u32,height:u32,}implRectangle{fnnew(width:u32,height:u32)->Self{Self{width,height}}fnarea(&self)->u32{self.width*self.height}fnscale(&mutself,factor:u32){self.width*=factor;self.height*=factor;}}fnmain(){letmutrect=Rectangle::new(10,20);println!("area = {}",rect.area());rect.scale(2);println!("scaled area = {}",rect.area());}枚举(enum)用于构造代数数据类型,常与模式匹配match联合使用。
enumMessage{Quit,Move{x:i32,y:i32},Write(String),}fnprocess(msg:Message){matchmsg{Message::Quit=>println!("quit"),Message::Move{x,y}=>println!("move {}, {}",x,y),Message::Write(s)=>println!("write: {}",s),}}示例:
traitSummary{fnsummarize(&self)->String;fnsummarize_default(&self)->String{String::from("(Read more...)")}}structNews{headline:String,location:String,}implSummaryforNews{fnsummarize(&self)->String{format!("{}, ({})",self.headline,self.location)}}fnnotify(item:&implSummary){// trait bound 写法 1println!("Breaking: {}",item.summarize());}fnnotify2<T:Summary>(item:&T){// 泛型约束写法println!("Breaking2: {}",item.summarize());}&impl Trait(或T: Trait)通常是静态分发(编译时单态化)。&dyn Trait是 trait object(动态分发),运行时通过虚表调用方法,允许不同类型在运行时统一处理。示例:
fnnotify_dyn(item:&dynSummary){println!("dyn: {}",item.summarize());}Box<T>:将数据放到堆上,单一所有者。Rc<T>:引用计数(单线程)。Arc<T>:原子引用计数(多线程)。RefCell<T>:允许在运行时进行可变借用检查(单线程),实现“内部可变性”。Mutex<T>:互斥锁,用于多线程可变访问。示例(Rc<RefCell<T>>):
usestd::rc::Rc;usestd::cell::RefCell;fnmain(){letdata=Rc::new(RefCell::new(5));letd1=Rc::clone(&data);*d1.borrow_mut()+=1;println!("{}",data.borrow());// 6}多线程示例(Arc<Mutex<T>>):
usestd::sync::{Arc,Mutex};usestd::thread;fnmain(){letcounter=Arc::new(Mutex::new(0));letmuthandles=vec![];for_in0..10{letc=Arc::clone(&counter);handles.push(thread::spawn(move||{letmutnum=c.lock().unwrap();*num+=1;}));}forhinhandles{h.join().unwrap();}println!("counter = {}",*counter.lock().unwrap());}注意:仅在需要共享可变所有权时使用这些类型。
示例与修复:
clone()(尽量避免 clone)。RefCell运行时借用冲突会 panic → 在使用RefCell时遵守借用规则,或改用其它策略。练习题:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str并写单元测试。Rc<RefCell<T>>实现一个共享计数器,并演示两个持有者修改它。Rectangle,为其派生Debug,PartialEq,Clone,并编写示例代码。进阶阅读:
std::rc,std::sync,std::cell等。✅ 小结:
- 所有权与借用是 Rust 安全与并发性的基石;理解它们对写出正确高效的 Rust 程序至关重要。
如果你希望,我可以把所有示例拆成examples/可运行示例,并帮你验证它们能否编译运行(我也可以把文档放到docs/下或仓库根目录)。