C++中真正的臨時(shí)對(duì)象是看不見的,它們不出現(xiàn)在你的源代碼中,臨時(shí)對(duì)象的產(chǎn)生在如下幾個(gè)時(shí)刻:
1. 用構(gòu)造函數(shù)作為隱式類型轉(zhuǎn)換函數(shù)時(shí),會(huì)創(chuàng)建臨時(shí)對(duì)象。
例:
class Integer
{
public:
Integer(int i)
:m_val(i)
{}
~Integer()
{}
private:
int m_val;
};
void Calculate(Integer itgr)
{
// do something
}
那么語句: int i = 10;
Calculate(i);
會(huì)產(chǎn)生一個(gè)臨時(shí)對(duì)象,作為實(shí)參傳遞到Calculate 函數(shù)中。
2. 建立一個(gè)沒有命名的非堆(non-heap)對(duì)象,也就是無名對(duì)象時(shí),會(huì)產(chǎn)生臨時(shí)對(duì)象。
如:
Integer& iref = Integer(5); //用無名臨時(shí)對(duì)象初始化一個(gè)引用,等價(jià)于
//Integer iref(5);
Integer itgr = Integer(5); //用一個(gè)無名臨時(shí)對(duì)象拷貝構(gòu)造另一個(gè)對(duì)象
按理說,C++應(yīng)先構(gòu)造一個(gè)無名的臨時(shí)對(duì)象,再用它來拷貝構(gòu)造itgr,由于
該臨時(shí)對(duì)象拷貝構(gòu)造 itgr 后,就失去了任何作用,所以對(duì)于這種類型(只起拷貝構(gòu)造另一個(gè)對(duì)象的作用)的臨時(shí)對(duì)象,c++特別將其看做: Integer itgr(5); 即直接以相同參數(shù)構(gòu)造目標(biāo)對(duì)象,省略了創(chuàng)建臨時(shí)對(duì)象這一步。
Calculate( Integer(5) ); //無名臨時(shí)對(duì)象作為實(shí)參傳遞給形參,函數(shù)調(diào)
//用表達(dá)式結(jié)束后,臨時(shí)對(duì)象生命期結(jié)束,被//析構(gòu).
3. 函數(shù)返回一個(gè)對(duì)象值時(shí),會(huì)產(chǎn)生臨時(shí)對(duì)象,函數(shù)中的返回值會(huì)以值拷貝的形式拷貝到被調(diào)函數(shù)棧中的一個(gè)臨時(shí)對(duì)象。
如:
Integer Func()
{
Integer itgr;
return itgr;
}
void main()
{
Integer in;
in = Func();
}
表達(dá)式 Func() 處創(chuàng)建了一個(gè)臨時(shí)對(duì)象,用來存儲(chǔ)Func() 函數(shù)中返回的對(duì)象,臨時(shí)對(duì)象由 Func() 中返回的 itgr 對(duì)象拷貝構(gòu)造(值傳遞),臨時(shí)對(duì)象賦值給 in后,賦值表達(dá)式結(jié)束,臨時(shí)對(duì)象被析構(gòu)。見下圖:

看看如下語句:
Integer& iRef = Func();
該語句用一個(gè)臨時(shí)對(duì)象去初始化iRef 引用,一旦該表達(dá)式執(zhí)行結(jié)束,臨時(shí)對(duì)象的生命周期結(jié)束,便被結(jié)束,iRef引用的尸體已經(jīng)不存在,接下來任何對(duì) iRef 的操作都是錯(cuò)誤的。
下面,來看看實(shí)際的測試結(jié)果,代碼如下:
class VECTOR3
{
public:
VECTOR3()
:x(0.0f),y(0.0f),z(0.0f)
{
std::cout<<"VECTOR3 Default Constructor "
<<std::setiosflags(std::ios_base::hex)<<this
<<std::endl;
}
VECTOR3(float fx, float fy, float fz)
:x(0.0f),y(0.0f),z(0.0f)
{
std::cout<<"VECTOR3 Parameter Constructor "
<<std::setiosflags(std::ios_base::hex)<<this
<<std::endl;
}
VECTOR3(const VECTOR3& rht)
:x(rht.x), y(rht.y), z(rht.z)
{
std::cout<<"VECTOR3 Copy Constructor "
<<std::setiosflags(std::ios_base::hex)<<this
<<" from rht : "
<<std::setiosflags(std::ios_base::hex)<<&rht
<<std::endl;
}
~VECTOR3()
{
std::cout<<"VECTOR3 Destructor "
<<std::setiosflags(std::ios_base::hex)<<this
<<std::endl;
}
VECTOR3& operator = (const VECTOR3& rht)
{
if( &rht == this )
return *this;
x = rht.x;
y = rht.y;
z = rht.z;
std::cout<<"VECTOR3 operator = left oper : "
<<std::setiosflags(std::ios_base::hex)<<this
<<" right oper : "
<<std::setiosflags(std::ios_base::hex)<<&rht
<<std::endl;
return *this;
}
private:
float x;
float y;
float z;
};
VECTOR3 Func1()
{
return VECTOR3(1.0f, 1.0f, 1.0f);
}
VECTOR3 Func2()
{
VECTOR3 ret;
ret.x = 2.0f;
ret.y = 2.0f;
ret.z = 2.0f;
return ret;
}
void main()
{
VECTOR3 v1 = Func1();
v1 = Func1();
VECTOR3 v2 = Func2();
VECTOR3 v3;
v3 = Func2();
}
分析:
<1>.
VECTOR3 v1 = Func1();
該語句的執(zhí)行過程本該是:
1>. 在 Func1() 中構(gòu)造一個(gè)無名對(duì)象
2>. 由 Func1() 中的無名對(duì)象拷貝構(gòu)造調(diào)用表達(dá)式處的臨時(shí)對(duì)象
3>. 再由臨時(shí)對(duì)象拷貝構(gòu)造v1
4>. Func1() 返回,析構(gòu)無名對(duì)象
5>. 整個(gè)語句結(jié)束,析構(gòu)臨時(shí)對(duì)象
但是c++ 會(huì)優(yōu)化上述過程,省略了 1>. 2>. 處的臨時(shí)對(duì)象創(chuàng)建,直接以
1.0f, 1.0f, 1.0f 為參數(shù)構(gòu)造v1,這樣只會(huì)有一次構(gòu)造函數(shù)的調(diào)用。結(jié)果
如圖:

<2>.
v1 = Func1();
該語句的執(zhí)行過程本該是:
1>. 在 Func1() 中構(gòu)造一個(gè)無名對(duì)象
2>. 由 Func1() 中的無名對(duì)象拷貝構(gòu)造調(diào)用表達(dá)式處的臨時(shí)對(duì)象
3>. 再由臨時(shí)對(duì)象賦值給v1 (賦值運(yùn)算符)
4>. Func1() 返回,析構(gòu)無名對(duì)象
5>. 整個(gè)語句結(jié)束,析構(gòu)臨時(shí)對(duì)象
但是c++ 會(huì)優(yōu)化上述過程,省略了 1>. 處的無名臨時(shí)對(duì)象創(chuàng)建,直接以
1.0f, 1.0f, 1.0f 為參數(shù)構(gòu)造調(diào)用表達(dá)式處的臨時(shí)對(duì)象,因?yàn)槭琴x值,所以這個(gè)臨時(shí)對(duì)象是無法被優(yōu)化的,賦值完畢后,表達(dá)式結(jié)束,臨時(shí)對(duì)象被析構(gòu)。結(jié)果如圖:

<3>.
VECTOR3 v2 = Func2();
該語句的執(zhí)行過程本該是:
1>. Func2() 中的 ret 拷貝構(gòu)造調(diào)用表達(dá)式處的臨時(shí)對(duì)象
2>. 該臨時(shí)對(duì)象拷貝構(gòu)造v2
3>. 析構(gòu)臨時(shí)對(duì)象
但是c++ 會(huì)優(yōu)化上述過程,省略了創(chuàng)建臨時(shí)對(duì)象這一步,直接由ret拷貝
構(gòu)造v2,就一次拷貝構(gòu)造函數(shù)的代價(jià)。
結(jié)果如圖:

<4>.
VECTOR3 v3;
v3 = Func2();
執(zhí)行過程如下:
1>. 構(gòu)造v3
2>. 進(jìn)入Func2(),構(gòu)造ret
3>. 返回ret,用ret拷貝構(gòu)造到調(diào)用表達(dá)式處的臨時(shí)對(duì)象
4>. Func2()結(jié)束,ret被析構(gòu)
5>. 臨時(shí)對(duì)象賦值給v3
6>. 賦值表達(dá)式結(jié)束,析構(gòu)臨時(shí)對(duì)象
結(jié)果如圖:

綜上所述,可得如下結(jié)論:
<1>. 在使用一個(gè)臨時(shí)對(duì)象( 可能是無名對(duì)象 或者 返回對(duì)象值時(shí) ) 創(chuàng)建構(gòu)造另一個(gè)對(duì)象的過程的中,c++會(huì)優(yōu)化掉該臨時(shí)對(duì)象的產(chǎn)生,直接以相同參數(shù)調(diào)用相關(guān)構(gòu)造函數(shù)構(gòu)或者 直接調(diào)用拷貝構(gòu)造函數(shù) 到 目標(biāo)對(duì)象.
<2>. 若不是對(duì)象創(chuàng)建,而是對(duì)象賦值,則在賦值表達(dá)式的右值處的臨時(shí)對(duì)象
創(chuàng)建不能省略,臨時(shí)對(duì)象賦值給左值后,表達(dá)式結(jié)束,臨時(shí)對(duì)象被析構(gòu)。
posted on 2010-02-25 14:44
李陽 閱讀(4764)
評(píng)論(6) 編輯 收藏 引用 所屬分類:
C++