C++:臨時量&臨時物件
阿新 • • 發佈:2018-12-31
臨時量
· 內建型別生成的臨時量是常量(臨時量,暫存器帶出來)。
· 自定義型別生成的臨時量是變數 ,在記憶體中。
· 隱式生成生成的臨時量是常量 ,顯式生成生成的臨時量是變數 。
臨時物件
臨時物件是系統臨時分配的物件,在沒主動宣告所需物件而又使用其功能時產生的。
何時產生臨時物件
1)以值的方式給函式傳參;
#include<iostream> class Test { public: Test(int a, int b) { std::cout << this << " :Test::Test(int,int)" << std::endl; ma = a; mb = b; } Test(int a) { std::cout << this << " :Test::Test(int)" << std::endl; ma = a; mb = 0; } Test() { std::cout << this << " :Test::Test()" << std::endl; ma = mb = 0; } Test(const Test& rhs) { std::cout << this << " :Test::Test(const Test&)" << std::endl; ma = rhs.ma; mb = rhs.mb; } Test& operator=(const Test& rhs) { std::cout << this << " :Test::operator=(const Test&)" << std::endl; if (this != &rhs) { ma = rhs.ma; mb = rhs.mb; } return *this; } ~Test() { std::cout << this << " :Test::~Test()" << std::endl; } private: int ma; int mb; }; void getObject(Test lhs) { } int main() { Test test1(10, 20);//呼叫了帶有兩個引數的建構函式 getObject(test1);//按值傳遞,已存在的物件生成一個相同型別的新(臨時)物件,呼叫拷貝建構函式創造了一個副本。 return 0; }
列印結果:
針對這種情況,將形參傳入物件引用,因為引用只是物件的一個別名,不會產生臨時物件,程式碼修改如下:
2)型別轉換;
#include<iostream> class Test { public: Test(int a, int b) { std::cout << this << " :Test::Test(int,int)" << std::endl; ma = a; mb = b; } Test(int a) { std::cout << this << " :Test::Test(int)" << std::endl; ma = a; mb = 0; } Test() { std::cout << this << " :Test::Test()" << std::endl; ma = mb = 0; } Test(const Test& rhs) { std::cout << this << " :Test::Test(const Test&)" << std::endl; ma = rhs.ma; mb = rhs.mb; } Test& operator=(const Test& rhs) { std::cout << this << " :Test::operator=(const Test&)" << std::endl; if (this != &rhs) { ma = rhs.ma; mb = rhs.mb; } return *this; } ~Test() { std::cout << this << " :Test::~Test()" << std::endl; } private: int ma; int mb; }; int main() { Test test1;//呼叫預設建構函式 test1=10;//表示式左右型別不匹配,右邊,已存在的物件先生成一個相同型別的新(臨時)物件,呼叫帶有一個引數的建構函式, //然後這個已存在的(臨時)物件賦值給相同型別的已存在的物件 return 0; }
列印結果:
針對這種情況,對main函式中的程式碼稍作修改,將不會產生臨時物件,程式碼修改如下:
這其實是一種優化: 即臨時物件生成的目的是為了生成新物件,則以生成臨時物件的方式來生成新物件。
原因:當我們定義Test test1時,在main的棧中為test1物件建立了一個預留的空間。而我們用10呼叫構造時,此時的構造是在為test1預留的空間中進行的,因此減少了一次臨時物件的建立。
3)函式需要返回一個物件時;
#include<iostream>
class Test
{
public:
Test(int a, int b)
{
std::cout << this << " :Test::Test(int,int)" << std::endl;
ma = a;
mb = b;
}
Test(int a)
{
std::cout << this << " :Test::Test(int)" << std::endl;
ma = a;
mb = 0;
}
Test()
{
std::cout << this << " :Test::Test()" << std::endl;
ma = mb = 0;
}
Test(const Test& rhs)
{
std::cout << this << " :Test::Test(const Test&)" << std::endl;
ma = rhs.ma;
mb = rhs.mb;
}
Test& operator=(const Test& rhs)
{
std::cout << this << " :Test::operator=(const Test&)" << std::endl;
if (this != &rhs)
{
ma = rhs.ma;
mb = rhs.mb;
}
return *this;
}
~Test()
{
std::cout << this << " :Test::~Test()" << std::endl;
}
int getValue()
{
return ma;
}
private:
int ma;
int mb;
};
Test getObject(Test &lhs)
{
Test tmp;//呼叫預設建構函式
tmp = lhs.getValue();//表示式右邊,呼叫帶有一個引數的建構函式,生成臨時物件,
//然後已存在的物件賦值給相同型別的已存在的函式,呼叫賦值運算子過載函式,
return tmp;//已存在的物件生成一個相同型別的新(臨時)物件,呼叫拷貝建構函式。
}
int main()
{
Test test1(10,20);//呼叫帶有兩個引數的建構函式
getObject(test1);
return 0;
}
列印結果:
針對這種情況,直接返回物件,發現減少了一次建構函式呼叫,一次拷貝建構函式呼叫和一次賦值拷貝函式呼叫。
return lhs.getValue(); 與Test tmp=lhs.getValue();等價
先呼叫帶有一個引數的建構函式,生成臨時物件,這個臨時物件生成的目的是為了生成新物件,故有優化。