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

大龍的博客

常用鏈接

統計

最新評論

C++中的臨時變量

C++中的臨時變量

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

C++的臨時變量是編譯器在需要的時候自動生成的臨時性變量,它們并不在代碼中出現.但是它們在編譯器生成的二進制編碼中是存在的,
也創建和銷毀.在C++語言中,臨時變量的問題格外的重要,因為每個用戶自定義類型的臨時變量都要出發用戶自定義的構造函數和析構函數(如果用戶提供了)

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

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

X a;
X b = get(a);
即使是這么簡單的代碼也是很難實現的
讓我們分析一下代碼執行過程中發生了什么?
首先我要告訴你一個秘密:對于一個函數來說,無論是傳入一個對象還是傳出一個對象其實都是不可能的.
讓一個函數傳入或傳出一個內置的數據類型,例如int,是很容易的,但是對于用戶自定義類型得對象卻非常的困難,因為編譯器總得找地方為這些對象
寫上構造函數和析構函數,不是在函數內,就是在函數外,除非你用指針或引用跳過這些困難

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

對于以對象為形參的函數:
void foo(X x0)
{
}
X xx;
foo(xx);
編譯器一般按照以下兩種轉換方式中的一種進行轉換
1.在函數外提供臨時變量
void foo(X& x0)    //修改foo的聲明為引用
{
}
X xx;         //聲明xx
X::X(xx);       //調用xx的默認構造函數
X __temp0;      //聲明臨時變量__temp0
X::X(__temp0, xx); //調用__temp0的拷貝構造函數
foo(__temp0);     //調用foo
X::~X(__temp0);    //調用__temp0的析構函數
X::~X(xx);      //調用xx的析構函數
2.在函數內提供臨時變量
void foo(X& x0)    //修改foo的聲明為引用
{
   X __temp0;      //聲明臨時變量__temp0
   X::X(__temp0, x0); //調用__temp0的拷貝構造函數
   X::~X(__temp0);    //調用__temp0的析構函數
}
X xx;         //聲明xx
X::X(xx);       //調用xx的默認構造函數
foo(xx);       //調用foo
X::~X(xx);      //調用xx的析構函數

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

X yy = foo();
編譯器一般按照以下方式進行轉換
void foo(X& __temp0) //修改foo的聲明為引用
{
   X xx;         //聲明xx
   X::X(xx);       //調用xx的默認構造函數
   __temp0::X::X(xx); //調用__temp0的拷貝構造函數
   X::~X(xx);      //調用xx的析構函數
}

X yy;          //聲明yy
X __temp0;       //聲明臨時變量__temp0
foo(__temp0);      //調用foo
X::X(yy, __temp0);   //調用yy的拷貝構造函數
X::~X(__temp0);     //調用__temp0的析構函數
X::~X(yy);       //調用yy的析構函數

既然我們已經聲明了yy,為什么還要緊接著聲明__temp0,其實這里完全可以把yy和臨時變量合一
優化后,上面的代碼看起來象這個樣子:
void foo(X& __temp0) //修改foo的聲明為引用
{
   X xx;         //聲明xx
   X::X(xx);       //調用xx的默認構造函數
   __temp0::X::X(xx); //調用__temp0的拷貝構造函數
   X::~X(xx);      //調用xx的析構函數
}

X yy;          //聲明yy
foo(yy);        //調用foo
X::~X(yy);       //調用yy的析構函數

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

為什么函數和臨時變量這么有緣,其實根本的原因在于對象傳值的語意,這一個也是為什么C++中鼓勵傳對象地址的原因

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

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

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

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

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

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

希望大家不要犯類似的錯誤

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


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   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>
            国产精品av免费在线观看 | 亚洲欧美制服中文字幕| 久久久久久久久久久一区| 欧美亚洲成人网| 日韩亚洲视频| 亚洲电影欧美电影有声小说| 亚洲一区二区在线免费观看| 欧美日韩三级一区二区| 99re6热在线精品视频播放速度| 欧美福利一区二区| 久久久一本精品99久久精品66| 国产日韩成人精品| 久久国产欧美| 久久露脸国产精品| 亚洲观看高清完整版在线观看| 欧美99久久| 欧美大胆成人| 99pao成人国产永久免费视频| 亚洲激情视频网| 欧美日韩不卡合集视频| 在线一区二区三区四区| 国产精品99久久99久久久二8| 国产精品极品美女粉嫩高清在线 | 欧美日韩在线播放| 一区二区欧美在线观看| 日韩亚洲欧美一区二区三区| 久久av一区二区三区| 一区二区三区四区五区在线| 国产精品第13页| 久久激情视频久久| 久久狠狠亚洲综合| 亚洲高清网站| 亚洲欧洲综合另类在线| 欧美亚男人的天堂| 久久久久国产精品麻豆ai换脸| 久久久久一区| 亚洲视频播放| 久久激情五月丁香伊人| 亚洲人成网站色ww在线| 在线综合亚洲欧美在线视频| 国产综合亚洲精品一区二| 亚洲第一伊人| 国产三级精品三级| 欧美国产日本在线| 国产精品美女久久久久久免费 | 亚洲天堂第二页| 黄色成人在线| 亚洲美女黄网| 国内视频一区| 日韩视频中文字幕| 永久免费精品影视网站| 香蕉久久夜色精品| 久久免费国产| 欧美日韩喷水| 久久综合久久综合这里只有精品| 欧美成人激情视频免费观看| 午夜精品久久| 欧美激情网站在线观看| 欧美一区观看| 欧美人牲a欧美精品| 久久久天天操| 国产精品日本精品| 最近看过的日韩成人| 国产综合香蕉五月婷在线| 日韩午夜免费视频| 亚洲大片一区二区三区| 亚洲欧美bt| 在线中文字幕一区| 美女精品视频一区| 久久久综合网站| 国产欧美精品在线| 亚洲午夜久久久| 亚洲午夜激情网站| 欧美欧美天天天天操| 欧美激情一区二区在线| 在线成人免费视频| 久久www成人_看片免费不卡| 欧美一乱一性一交一视频| 欧美三级在线视频| 亚洲精品人人| 一区二区三区欧美日韩| 欧美激情一区二区三区在线| 欧美高清视频一区| 亚洲电影中文字幕| 久久综合九色综合久99| 蜜桃伊人久久| 亚洲国产毛片完整版| 美女露胸一区二区三区| 亚洲高清av| 一区二区三区产品免费精品久久75 | 久久在线观看视频| 国产在线不卡| 久久精品国产一区二区电影| 久久久久久久高潮| 黄色成人精品网站| 久久视频精品在线| 牛人盗摄一区二区三区视频| 尹人成人综合网| 麻豆精品精华液| 欧美国产视频日韩| 亚洲精品视频二区| 欧美日韩免费观看中文| 亚洲色图在线视频| 欧美在线观看天堂一区二区三区| 国产欧美日韩免费| 久久久999精品免费| 欧美激情第二页| 亚洲视频在线一区观看| 国产精品入口尤物| 久久久精品动漫| 亚洲黄色大片| 亚洲女ⅴideoshd黑人| 国产色视频一区| 每日更新成人在线视频| 日韩亚洲欧美一区| 久久久久久9999| 亚洲精品一区中文| 国产精品免费福利| 亚洲欧美日产图| 久久免费视频在线观看| 欧美在线观看一二区| 亚洲老板91色精品久久| 欧美三级欧美一级| 亚洲视频中文字幕| 麻豆av一区二区三区| 亚洲一区久久| 国产精品自拍网站| 伊人久久大香线蕉av超碰演员| 亚洲人成网在线播放| 极品尤物久久久av免费看| 亚洲欧美日韩精品久久奇米色影视| 宅男噜噜噜66国产日韩在线观看| 久久永久免费| 女人天堂亚洲aⅴ在线观看| 国产视频亚洲| 欧美伊人久久久久久久久影院 | 韩国自拍一区| 性做久久久久久| 久久先锋影音av| 伊人男人综合视频网| 久久亚洲综合网| 亚洲夫妻自拍| 日韩午夜av电影| 欧美日精品一区视频| 在线综合+亚洲+欧美中文字幕| 亚洲视频在线观看| 国产精品一区2区| 久久久精品日韩| 欧美激情黄色片| 一本色道久久综合亚洲精品不卡 | 国产中文一区| 久久综合久久久| 亚洲精品视频在线播放| 亚洲免费在线看| 国产一区二区高清| 中文久久精品| 欧美日韩国产探花| 亚洲一级免费视频| 久久精品国产免费看久久精品| 国产亚洲精品久久飘花| 久久久久久有精品国产| 亚洲国产精品久久| 亚洲午夜视频在线| 好吊色欧美一区二区三区四区| 欧美91大片| 亚洲午夜精品一区二区| 免费国产一区二区| 亚洲一区二区网站| 亚洲电影免费在线观看| 欧美日韩综合网| 久久久爽爽爽美女图片| 国产尤物精品| 在线精品福利| 欧美日韩视频在线一区二区观看视频| 一本色道久久综合一区| 麻豆av一区二区三区久久| 亚洲色在线视频| 伊人精品久久久久7777| 欧美午夜不卡在线观看免费 | 免费观看日韩av| 亚洲字幕在线观看| 亚洲大片在线| 国产麻豆日韩| 欧美另类专区| 久久精品欧美日韩| 亚洲图片在线观看| 亚洲激情电影中文字幕| 久久九九精品99国产精品| 亚洲视频axxx| 亚洲另类在线视频| 18成人免费观看视频| 国产日韩欧美在线观看| 欧美午夜在线| 欧美日韩三级视频| 欧美激情国产日韩| 久久午夜视频| 久久久久久久一区二区三区| 性色av香蕉一区二区| 亚洲自拍偷拍视频| 中文精品视频一区二区在线观看|