本系列文章是Jon Gjengset發(fā)布的CRust of Rust系列視頻的學(xué)習(xí)筆記,CRust of Rust是一系列持續(xù)更新的Rust中級(jí)教程。
讓我們接著上一篇文章繼續(xù)學(xué)習(xí)Rust的生命周期。在上一篇文章中的代碼基礎(chǔ)上,加入如下的函數(shù)和測(cè)試用例:
1fnuntil_char(s:&str,c:char)->&str{ 2StrSplit::new(s,&format!("{}",c)) 3.next() 4.expect("StrSplitalwaysgivesatleastoneresult") 5} 6 7#[test] 8fnuntil_char_test(){ 9assert_eq!(until_char("helloworld",'o'),"hell"); 10}編譯器會(huì)報(bào)如下錯(cuò)誤:
error[E0515]: cannot return value referencing temporary value
這里的臨時(shí)值是&format!("{}",c),從代碼中可以看出,參數(shù)s、c和next()之后的值要擁有相同的生命周期,因此返回值與臨時(shí)值的生命周期相同。但是這個(gè)臨時(shí)值的生命周期在函數(shù)執(zhí)行完后就結(jié)束了,所以編譯不通過。
有一種解決辦法是使用String
1#[derive(Debug)]
2pubstructStrSplit<'a>{
3//使用Option
4remainder:Option<&'a?str>,
5delimiter:String,
6}
但是使用String是有兩個(gè)問題的,我們先來比較一下str,&str,String之間的區(qū)別:
str -> [char]:相當(dāng)于char類型的切片,既可以分配在棧上,也可以分配在堆上,還可以分配在static區(qū)。
&str -> &[char]:相當(dāng)于胖指針,包含指向str的指針和字符串的長(zhǎng)度。
String -> Vec
String轉(zhuǎn)換&str相對(duì)容易一些,因?yàn)橐阎址钠鹗嘉恢眉伴L(zhǎng)度。而&str轉(zhuǎn)換成String就復(fù)雜一些,需要先在堆上分配一段空間,然后再通過內(nèi)存拷貝(memcpy)把字符copy到堆上。
因此使用String的第一個(gè)問題是性能問題;第二個(gè)問題是不能兼容嵌入式系統(tǒng),大多數(shù)嵌入式系統(tǒng)沒有堆內(nèi)存。
我們選擇更好的解決方案,定義多個(gè)生命周期
1#[derive(Debug)]
2pubstructStrSplit<'haystack,?'delimiter>{
3//使用Option
4remainder:Option<&'haystack?str>,
5delimiter:&'delimiterstr,
6}
1impl<'haystack,?'delimiter>StrSplit<'haystack,?'delimiter>{
2/**
3*新構(gòu)建的StrSplit與傳入的參數(shù)haystack,delimiter擁有相同的生命周期
4*/
5pubfnnew(haystack:&'haystackstr,delimiter:&'delimiterstr)->Self{
6Self{
7remainder:Some(haystack),
8delimiter,
9}
10}
11}
12
13impl<'haystack>IteratorforStrSplit<'haystack,?'_>{
14//迭代的結(jié)果也要與StrSplit擁有相同的生命周期,是因?yàn)橐赟trSplit的成員remainder上做迭代。
15typeItem=&'haystackstr;
16
17fnnext(&mutself)->Option{
18letremainder=self.remainder.as_mut()?;
19ifletSome(next_delim)=remainder.find(self.delimiter){
20letuntil_remainder=&remainder[..next_delim];
21*remainder=&remainder[next_delim+self.delimiter.len()..];
22Some(until_remainder)
23}else{
24self.remainder.take()
25}
26}
27}
執(zhí)行cargo test,測(cè)試通過。 泛型化Delimiter 在這里我們將分隔符進(jìn)行泛型化,使得StrSplit更加通用。
1pubstructStrSplit<'haystack,?D>{
2//使用Option
3remainder:Option<&'haystack?str>,
4delimiter:D,
5}
6
7impl<'haystack,?D>StrSplit<'haystack,?D>{
8pubfnnew(haystack:&'haystackstr,delimiter:D)->Self{
9Self{
10remainder:Some(haystack),
11delimiter,
12}
13}
14}
定義一個(gè)trait,包含一個(gè)find_next()方法,用于返回分隔符在字符串中的起始位置和結(jié)束位置
1pubtraitDelimiter{
2//返回分隔符在字符串中的起始位置和結(jié)束位置
3fnfind_next(&self,s:&str)->Option<(usize,?usize)>;
4}
迭代器修改如下:
1impl<'haystack,?D>IteratorforStrSplit<'haystack,?D>
2where
3D:Delimiter
4{
5//迭代的結(jié)果也要與StrSplit擁有相同的生命周期,是因?yàn)橐赟trSplit的成員remainder上做迭代。
6typeItem=&'haystackstr;
7
8fnnext(&mutself)->Option{
9letremainder=self.remainder.as_mut()?;
10ifletSome((delim_start,delim_end))=self.delimiter.find_next(remainder){
11letuntil_remainder=&remainder[..delim_start];
12*remainder=&remainder[delim_end..];
13Some(until_remainder)
14}else{
15self.remainder.take()
16}
17}
18}
然后為&str和char分別實(shí)現(xiàn)Delimiter trait:
1implDelimiterfor&str{ 2fnfind_next(&self,s:&str)->Option<(usize,?usize)>{ 3s.find(self).map(|start|(start,start+self.len())) 4} 5} 6 7implDelimiterforchar{ 8fnfind_next(&self,s:&str)->Option<(usize,?usize)>{ 9s.char_indices() 10.find(|(_,c)|c==self) 11.map(|(start,_)|(start,start+self.len_utf8())) 12} 13}函數(shù)until_char()修改為:
1pubfnuntil_char(s:&str,c:char)->&str{
2StrSplit::new(s,c)
3.next()
4.expect("StrSplitalwaysgivesatleastoneresult")
5}
執(zhí)行cargo test,測(cè)試通過。
審核編輯:湯梓紅
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4404瀏覽量
66631 -
生命周期
+關(guān)注
關(guān)注
0文章
18瀏覽量
7547 -
Rust
+關(guān)注
關(guān)注
1文章
238瀏覽量
7459
原文標(biāo)題:CRust學(xué)習(xí)筆記:生命周期-2
文章出處:【微信號(hào):Rust語言中文社區(qū),微信公眾號(hào):Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
基于Rust語言中的生命周期
KaihongOS操作系統(tǒng):頁(yè)面的生命周期介紹
ServiceAbility的生命周期介紹
AutoScaling 生命周期掛鉤功能
HarmonyOS應(yīng)用開發(fā)-PageAbility生命周期介
在S32G2 RM中有“生命周期”,生命周期的完整含義是什么?
一文讀懂Android Activity生命周期
CRust學(xué)習(xí)筆記:生命周期-1
CRust學(xué)習(xí)筆記:聲明宏
CRust學(xué)習(xí)筆記:智能指針和內(nèi)部可變性
鴻蒙開發(fā):【PageAbility的生命周期】

CRust學(xué)習(xí)筆記:生命周期-2
評(píng)論