将值传递给函数在语义上和把值赋给变量是类似的。 把值传递给函数将发生移动或复制,例:fnmain(){letsString::from(hello);takeownership(s);letn666;makescopy(n);println!(n:{},n);println!(s:{},s);}fntakeownership(str:String){println!(str:{},str);}fnmakescopy(number:i32){println!(number:{},number);} build以上代码,编译器将提示错误:error〔E0382〕:borrowofmovedvalue:ssrcmain。rs:8:232letsString::from(hello);moveoccursbecauseshastypeString,whichdoesnotimplementtheCopytrait3takeownership(s);valuemovedhere。。。8println!(s:{},s);valueborrowedhereaftermoveFormoreinformationaboutthiserror,tryrustcexplainE0382。error:couldnotcompilerustlearningduetopreviouserror 根据提示可以看出:fnmain(){letsString::from(hello);takeownership(s);s的值移动到了函数里,所以s失效,s在后面就不可再次使用。letn666;makescopy(n);x本该也移动至函数,但i32是可Copy的,所以这里发生的是复制,因此x在后面还可使用。println!(n:{},n);println!(s:{},s);}fntakeownership(str:String){str进入作用域println!(str:{},str);}离开作用域,Rust调用drop方法,str的堆内存被释放fnmakescopy(number:i32){number(由n复制的副本)进入作用域println!(number:{},number);}i32是完全存储在栈上的数据,所以离开作用域后被弹出栈即可,不需释放堆内存。返回值与作用域 函数在返回值的过程中也会发生所有权的转移。例:fnmain(){lets1giveownership();giveownership将返回值所有权移动给s1lets2String::from(hello);s2进入作用域lets3takeandgiveback(s2);s2被移动到函数takeandgiveback里函数又将返回值移动给s3println!({}{}{},s1,s2,s3)由于s2已被移动至函数takeandgiveback里,所以此处s2无效}fngiveownership()String{letstrString::from(hello);str返回str并将其所有权移出给调用它的函数}fntakeandgiveback(str:String)String{str返回str并将其所有权移出给调用它的函数} 一个变量的所有权总是遵循同样的模式:把一个值赋给其它变量时就会发生移动(可Copy的变量发生复制)当一个包含堆内存上数据的变量离开作用域时,它会被drop方法释放,除非其所有权移动到另一个变量上了 如何让函数使用某个值,但不获得其所有权?一种做法是将值传入函数,函数用完后再将其移动回来。例:fnmain(){lets1String::from(hello);let(s2,len)calculatelength(s1);println!(Thelengthof{}is{}。,s2,len);}fncalculatelength(s:String)(String,usize){letlengths。len();(s,length)} 但这种实现看起来不够优雅,所以Rust有一个特性叫做引用(Reference)对于引用的概念及用法将在下一节继续。