青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大龍的博客

常用鏈接

統(tǒng)計(jì)

最新評(píng)論

C++中的臨時(shí)變量

C++中的臨時(shí)變量

它們是被神所遺棄的孩子,沒有人見過(guò)它們,更沒有人知道它們的名字.它們命中注定徘徊于命運(yùn)邊緣高聳的懸崖和幽深的深淵之間,
用自己短暫的生命撫平了生與死之間的縫隙.譬如朝露,卻與陽(yáng)光無(wú)緣.是該為它們立一座豐碑的時(shí)候了,墓銘志上寫著:我來(lái)了,我走了,我快樂(lè)過(guò).
許多人對(duì)臨時(shí)變量的理解僅僅限于:
string temp;
其實(shí),從C++的觀點(diǎn)來(lái)看,這根本就不是臨時(shí)變量,而是局部變量.

C++的臨時(shí)變量是編譯器在需要的時(shí)候自動(dòng)生成的臨時(shí)性變量,它們并不在代碼中出現(xiàn).但是它們?cè)诰幾g器生成的二進(jìn)制編碼中是存在的,
也創(chuàng)建和銷毀.在C++語(yǔ)言中,臨時(shí)變量的問(wèn)題格外的重要,因?yàn)槊總€(gè)用戶自定義類型的臨時(shí)變量都要出發(fā)用戶自定義的構(gòu)造函數(shù)和析構(gòu)函數(shù)(如果用戶提供了)

又是該死的編譯器!又該有人抱怨編譯器總在自己背后干著偷偷摸摸的事情了.但是如果離開了編譯器的這些工作,我們可能寸步難行.

如果X是一個(gè)用戶自定義的類型,有默認(rèn)構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),賦值運(yùn)算函數(shù),析構(gòu)函數(shù)(這也是類的4個(gè)基本函數(shù)),那么請(qǐng)考慮以下代碼:
X get(X arg)
{
   return arg;
}

X a;
X b = get(a);
即使是這么簡(jiǎn)單的代碼也是很難實(shí)現(xiàn)的
讓我們分析一下代碼執(zhí)行過(guò)程中發(fā)生了什么?
首先我要告訴你一個(gè)秘密:對(duì)于一個(gè)函數(shù)來(lái)說(shuō),無(wú)論是傳入一個(gè)對(duì)象還是傳出一個(gè)對(duì)象其實(shí)都是不可能的.
讓一個(gè)函數(shù)傳入或傳出一個(gè)內(nèi)置的數(shù)據(jù)類型,例如int,是很容易的,但是對(duì)于用戶自定義類型得對(duì)象卻非常的困難,因?yàn)榫幾g器總得找地方為這些對(duì)象
寫上構(gòu)造函數(shù)和析構(gòu)函數(shù),不是在函數(shù)內(nèi),就是在函數(shù)外,除非你用指針或引用跳過(guò)這些困難

那么怎么辦?在這里,編譯器必須玩一些必要的小花招,嗯,其中的關(guān)鍵恰恰就是臨時(shí)變量

對(duì)于以對(duì)象為形參的函數(shù):
void foo(X x0)
{
}
X xx;
foo(xx);
編譯器一般按照以下兩種轉(zhuǎn)換方式中的一種進(jìn)行轉(zhuǎn)換
1.在函數(shù)外提供臨時(shí)變量
void foo(X& x0)    //修改foo的聲明為引用
{
}
X xx;         //聲明xx
X::X(xx);       //調(diào)用xx的默認(rèn)構(gòu)造函數(shù)
X __temp0;      //聲明臨時(shí)變量__temp0
X::X(__temp0, xx); //調(diào)用__temp0的拷貝構(gòu)造函數(shù)
foo(__temp0);     //調(diào)用foo
X::~X(__temp0);    //調(diào)用__temp0的析構(gòu)函數(shù)
X::~X(xx);      //調(diào)用xx的析構(gòu)函數(shù)
2.在函數(shù)內(nèi)提供臨時(shí)變量
void foo(X& x0)    //修改foo的聲明為引用
{
   X __temp0;      //聲明臨時(shí)變量__temp0
   X::X(__temp0, x0); //調(diào)用__temp0的拷貝構(gòu)造函數(shù)
   X::~X(__temp0);    //調(diào)用__temp0的析構(gòu)函數(shù)
}
X xx;         //聲明xx
X::X(xx);       //調(diào)用xx的默認(rèn)構(gòu)造函數(shù)
foo(xx);       //調(diào)用foo
X::~X(xx);      //調(diào)用xx的析構(gòu)函數(shù)

無(wú)論是在函數(shù)的內(nèi)部聲明臨時(shí)變量還是在函數(shù)的外部聲明臨時(shí)變量,其實(shí)都是差不多的,這里的含義是說(shuō)既然參數(shù)要以傳值的
語(yǔ)意傳入函數(shù),也就是實(shí)參xx其實(shí)并不能修改,那么我們就用一個(gè)一摸一樣臨時(shí)變量來(lái)移花接木,完成這個(gè)傳值的語(yǔ)意
但是這樣做也不是沒有代價(jià),編譯器要修改函數(shù)的聲明,把對(duì)象改為對(duì)象的引用,同時(shí)修改所有函數(shù)調(diào)用的地方,代價(jià)確實(shí)巨大啊,
但是這只是編譯器不高興而已,程序員和程序執(zhí)行效率卻沒有影響
對(duì)于以對(duì)象為返回值的函數(shù):
X foo()
{
   X xx;
   return xx;
}

X yy = foo();
編譯器一般按照以下方式進(jìn)行轉(zhuǎn)換
void foo(X& __temp0) //修改foo的聲明為引用
{
   X xx;         //聲明xx
   X::X(xx);       //調(diào)用xx的默認(rèn)構(gòu)造函數(shù)
   __temp0::X::X(xx); //調(diào)用__temp0的拷貝構(gòu)造函數(shù)
   X::~X(xx);      //調(diào)用xx的析構(gòu)函數(shù)
}

X yy;          //聲明yy
X __temp0;       //聲明臨時(shí)變量__temp0
foo(__temp0);      //調(diào)用foo
X::X(yy, __temp0);   //調(diào)用yy的拷貝構(gòu)造函數(shù)
X::~X(__temp0);     //調(diào)用__temp0的析構(gòu)函數(shù)
X::~X(yy);       //調(diào)用yy的析構(gòu)函數(shù)

既然我們已經(jīng)聲明了yy,為什么還要緊接著聲明__temp0,其實(shí)這里完全可以把yy和臨時(shí)變量合一
優(yōu)化后,上面的代碼看起來(lái)象這個(gè)樣子:
void foo(X& __temp0) //修改foo的聲明為引用
{
   X xx;         //聲明xx
   X::X(xx);       //調(diào)用xx的默認(rèn)構(gòu)造函數(shù)
   __temp0::X::X(xx); //調(diào)用__temp0的拷貝構(gòu)造函數(shù)
   X::~X(xx);      //調(diào)用xx的析構(gòu)函數(shù)
}

X yy;          //聲明yy
foo(yy);        //調(diào)用foo
X::~X(yy);       //調(diào)用yy的析構(gòu)函數(shù)

嗯,怎么說(shuō)呢,這算是一種優(yōu)化算法吧,其實(shí)這各個(gè)技巧已經(jīng)非常普遍了,并擁有一個(gè)專門的名稱Named Return Value(NRV)優(yōu)化
NRV優(yōu)化如今被視為標(biāo)準(zhǔn)C++編譯器的一個(gè)義不容辭的優(yōu)化操作(雖然其需求其實(shí)超出了正式標(biāo)準(zhǔn)之外)
除了以類為參數(shù)以外,如果參數(shù)的類型是const T&類型,這也可能導(dǎo)致臨時(shí)變量
void fun(const string& str)
const char* name = "wgs";
fun(name);
嗯,還記得在const文檔中的論述嗎?對(duì)于這種特殊的參數(shù)類型,編譯器是很樂(lè)意為你做自動(dòng)轉(zhuǎn)換的工作的,代價(jià)嘛,就是一個(gè)臨時(shí)變量,
不過(guò)如果是你自己去做,大概就只能聲明一個(gè)局部變量了

為什么函數(shù)和臨時(shí)變量這么有緣,其實(shí)根本的原因在于對(duì)象傳值的語(yǔ)意,這一個(gè)也是為什么C++中鼓勵(lì)傳對(duì)象地址的原因

和函數(shù)的情況類似的,還有一大類情況是臨時(shí)變量的樂(lè)土,那就是表達(dá)式
string s,t;
printf("%s", s + t);
這里s+t的結(jié)果該放在什么地方呢?只能是臨時(shí)變量中.

這個(gè)printf語(yǔ)句帶來(lái)了新的問(wèn)題,那就是"臨時(shí)變量的生命期"是如何的?
對(duì)于函數(shù)的情況,我們已經(jīng)看到了,臨時(shí)變量在完成交換內(nèi)容的使命后都是盡量早的被析構(gòu)了,那么對(duì)于表達(dá)式呢?
如果在s+t計(jì)算后析構(gòu),那么print函數(shù)打印的就是一個(gè)非法內(nèi)容了,因此C++給出的規(guī)則是:
臨時(shí)變量應(yīng)該在導(dǎo)致臨時(shí)變量創(chuàng)建的"完整表達(dá)式"求值過(guò)程的最后一個(gè)步驟被析構(gòu)
什么又是"完整表達(dá)式"?簡(jiǎn)單的說(shuō),就是不是表達(dá)式的子表達(dá)式
這條規(guī)則聽起來(lái)很簡(jiǎn)單,但具體實(shí)現(xiàn)起來(lái)就非常的麻煩了,例如:
X foo(int n)
if (foo(1) || foo(2) || foo(3) )
其中X中有operator int()轉(zhuǎn)換,所以可以用在if語(yǔ)句中
這里的foo(1)將產(chǎn)生一個(gè)臨時(shí)變量1,如果這部分為false,foo(2)將繼續(xù)產(chǎn)生一個(gè)臨時(shí)變量,如果這部分也為false,foo(3)...
一個(gè)臨時(shí)變量的參數(shù)居然是和運(yùn)行時(shí)相關(guān)的,更要命的是你要記住你到底產(chǎn)生了幾個(gè)臨時(shí)變量并在這個(gè)表達(dá)式結(jié)束的時(shí)候進(jìn)行析構(gòu)以小心的維護(hù)對(duì)象構(gòu)造和析構(gòu)的一致
我猜想,這里會(huì)展開成一段復(fù)雜的代碼,并加入更多的if判斷才能搞定,呵呵,好在我不是做編譯器的

上面的規(guī)則其實(shí)還有兩條例外:
string s,t;
string v = 1 ? s + t : s - t;
這里完整表達(dá)式是?語(yǔ)句,但是在完整表達(dá)式結(jié)束以后臨時(shí)變量還不能立即銷毀,而必須在變量v賦值完成后才能銷毀,這就是例外規(guī)則1:
凡含有表達(dá)式執(zhí)行結(jié)果的臨時(shí)變量,應(yīng)該存留到對(duì)象的初始化操作完成后銷毀

string s,t;
string& v = s + t;
這里s+t產(chǎn)生的臨時(shí)變量即使在變量v的賦值完成后也不能銷毀,否則這個(gè)引用就沒用了,這就是例外規(guī)則2:
如果一個(gè)臨時(shí)變量被綁定到一個(gè)引用,這個(gè)臨時(shí)變量應(yīng)該留到這個(gè)臨時(shí)變量和這個(gè)引用那個(gè)先超出變量的作用域后才銷毀

這篇文章可能有些深?yuàn)W了,畢竟大多數(shù)內(nèi)容來(lái)自于<<Inside The C++ Object Model>>
那么就留下一條忠告:
在stl中,以下的代碼是錯(cuò)誤的
string getName();
char* pTemp = getName().c_str();
getName返回的就是一個(gè)臨時(shí)變量,在把它內(nèi)部的char指針賦值給pTemp后析構(gòu)了,這時(shí)pTemp就是一個(gè)非法地址
確實(shí)如C++發(fā)明者Bjarne Stroustrup所說(shuō),這種情況一般發(fā)生在不同類型的相互轉(zhuǎn)換上

在Qt中,類似的代碼是這樣的
QString getName();
char* pTemp = getName().toAscii().data();
這時(shí)pTemp是非法地址

希望大家不要犯類似的錯(cuò)誤

posted on 2009-09-25 12:57 大龍 閱讀(633) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区视频| 久久久成人网| 99成人精品| 久久一区国产| 亚洲欧美国产三级| 欧美日韩视频免费播放| 在线观看欧美| 久久亚洲精品网站| 亚洲午夜激情| 国产精品v亚洲精品v日韩精品 | 亚洲人成毛片在线播放女女| 午夜宅男久久久| av成人福利| 欧美日韩国产成人| 亚洲免费黄色| 亚洲精品视频在线观看网站| 欧美成人精品在线| 亚洲美女毛片| 亚洲精品一区中文| 欧美精品一区视频| 在线亚洲免费| 欧美一区二区播放| 一区二区三区在线免费视频| 99综合视频| 亚洲美女网站| 国产精品高清免费在线观看| 亚洲一区二区欧美日韩| 在线视频精品| 国产伦精品一区二区三区免费 | 亚洲视频第一页| 亚洲精品影院在线观看| 欧美午夜大胆人体| 欧美一区二区三区播放老司机| 亚洲尤物在线视频观看| 国产视频久久久久| 欧美刺激午夜性久久久久久久| 女主播福利一区| 亚洲视频综合| 欧美在线视频免费播放| 亚洲福利一区| 99re6热在线精品视频播放速度| 国产精品第13页| 久久国产精品一区二区| 久久久99免费视频| 在线一区二区日韩| 性伦欧美刺激片在线观看| 国内精品国产成人| 亚洲国产天堂久久综合网| 欧美岛国激情| 午夜日韩在线观看| 快播亚洲色图| 亚洲一区二区少妇| 久久99在线观看| 亚洲美女黄色| 性一交一乱一区二区洋洋av| 亚洲国产日韩欧美在线99| 99国产精品久久久久久久| 国产欧美日韩亚洲精品| 欧美激情a∨在线视频播放| 欧美日韩中文字幕日韩欧美| 久久久精彩视频| 欧美精品1区| 久久精品视频在线播放| 欧美日韩午夜| 免费成人美女女| 国产精品国产三级国产aⅴ浪潮| 免费成人网www| 国产精品美女久久| 亚洲国产欧美精品| 国产日韩精品在线| 亚洲精一区二区三区| 在线成人国产| 午夜亚洲性色视频| 亚洲午夜在线观看视频在线| 蜜臀久久99精品久久久画质超高清 | 欧美日韩亚洲激情| 欧美夫妇交换俱乐部在线观看| 国产精品久久久久999| 亚洲成人在线免费| 亚洲成人自拍视频| 国产日韩欧美一区在线| 亚洲人成在线观看网站高清| 国产专区欧美精品| 亚洲综合视频一区| 中国成人亚色综合网站| 欧美国产欧美亚洲国产日韩mv天天看完整| 欧美在线视频免费| 国产麻豆9l精品三级站| 一区二区高清在线观看| aa级大片欧美| 欧美啪啪一区| 日韩亚洲视频在线| 亚洲综合激情| 国产精品任我爽爆在线播放 | 国产色产综合产在线视频| 一本色道久久综合亚洲精品按摩 | 亚洲国产日韩综合一区| 久久精品欧美日韩精品| 久久久久成人网| 国产真实久久| 久久久久久婷| 亚洲电影观看| 一本色道久久综合亚洲精品不卡| 欧美日本一区二区三区| 一级日韩一区在线观看| 亚洲摸下面视频| 国产精品一二三四| 久久成人精品无人区| 女生裸体视频一区二区三区 | 欧美高清视频在线| 亚洲激情不卡| 欧美国内亚洲| 欧美激情aⅴ一区二区三区| 欧美日韩久久不卡| 久久久久国色av免费观看性色| 欧美日韩在线免费视频| 亚洲激情网站| av不卡在线| 欧美精品v国产精品v日韩精品| 女同性一区二区三区人了人一| 伊人成年综合电影网| 久久久久久久尹人综合网亚洲| 免费观看成人www动漫视频| 国产一区二区三区日韩欧美| 欧美一区二区免费| 久久蜜臀精品av| 在线看片第一页欧美| 欧美专区第一页| 午夜精品久久久久久99热软件| 亚洲午夜视频在线观看| 1000部国产精品成人观看| 欧美激情亚洲综合一区| 亚洲电影免费观看高清完整版在线观看 | 亚洲国产精品一区二区www| 亚洲伦理在线观看| 在线视频欧美日韩精品| 国产精品久久久久久模特| 久久国产欧美| 欧美激情一区二区久久久| 日韩午夜在线观看视频| 欧美日韩在线一区二区三区| 亚洲你懂的在线视频| 亚洲第一二三四五区| 99精品欧美一区| 国产亚洲激情视频在线| 老色鬼久久亚洲一区二区| 亚洲精品久久久久久久久久久久| 一区二区三区精密机械公司| 国产精品视频导航| 中日韩高清电影网| 欧美激情一区二区三区四区| 国产精品99久久久久久www| 国产欧美日韩麻豆91| 男人的天堂亚洲| 亚洲尤物影院| 中文国产成人精品久久一| 久久久久久久久一区二区| 日韩亚洲欧美高清| 国产欧美一区二区三区国产幕精品| 久久精品电影| 最近中文字幕mv在线一区二区三区四区| 久久大逼视频| aa级大片欧美三级| 国产综合色产| 国产精品theporn88| 午夜影视日本亚洲欧洲精品| 亚洲网站视频福利| 欧美激情视频网站| 欧美一区高清| 一区二区三区免费网站| 免费成人黄色| 卡一卡二国产精品| 午夜精品亚洲| 99精品欧美一区二区三区| 欧美成人精品一区二区三区| 午夜精品福利视频| 99精品福利视频| 亚洲国产精品电影在线观看| 国产欧美在线播放| 国产精品国色综合久久| 欧美精品久久久久久久免费观看| 亚洲免费大片| 亚洲国产91色在线| 免费成人高清在线视频| 久久精品久久99精品久久| 久久久xxx| 久久精品视频网| 久久se精品一区精品二区| 亚洲午夜电影| 亚洲人成人一区二区在线观看 | 翔田千里一区二区| 亚洲美女淫视频| 91久久精品一区二区三区| 很黄很黄激情成人| 亚洲成人直播| 亚洲福利视频三区| 亚洲国产精品久久久久秋霞不卡| 国产一区二区三区四区hd| 欧美成人免费大片| 午夜在线精品|