一、拷貝構造函數
1、拷貝構造函數定義
class A { private: int _a;
public: A(){}; A(const A&); //定義拷貝構造函數,一定要有一個實現 };
A::A(const A& Aa) { cout<<"拷貝構造"<<endl; }
2、調用拷貝構造函數的時機
//E1、聲明語句中,一個對象初始化另一個對象,前提是類必須存在拷貝構造函數 A obj1; A obj2 = obj1; //E2、對象作爲參數 void get(A obj) {} //調用這個函數的時候,先會調用拷貝構造函數 //E3、函數返回一個對象 A get(){ A obj ; return obj;} //
二、C++淺拷貝和深拷貝【7】
1、淺拷貝
class A
{
private:
int _a;
public:
A(){};
A(const A&);
void setData(int a1){ _a = a1; }
void Output(){ cout<<"A::a = "<<_a<<endl; }
};
A::A(const A& Aa) //如果是淺拷貝,則,在這裏直接將一個對象的值賦值給另外一個對象
{
_a = Aa._a;
cout<<"拷貝構造"<<endl;
}
int main(int argc, char* argv[])
{
A a;
a.setData(10);
A b = a;
b.Output();
}
2、深拷貝
CExample::CExample(const CExample& RightSides)
{
pBuffer=NULL;
*this=RightSides //調用重載後的"="
}
//賦值操作符重載
CExample & CExample::operator = (const CExample& RightSides)
{
nSize=RightSides.nSize; //複製常規成員
char *temp=new char[nSize]; //複製指針指向的內容
memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));
delete []pBuffer; //刪除原指針指向內容 (將刪除操作放在後面,避免X=X特殊情況下,內容的丟失)
pBuffer=temp; //建立新指向
return *this
}
【點評】深拷貝,會將對象指針指向的動態內存中的值,拷貝到另外一個對象中,以防止內存泄露。另外,拷貝是將一個有值的對象賦值給空值的對象,而"賦值"操作符是將原來有值的對象中的值覆蓋,調用的是"=重載函數"。
三、拷貝構造函數調用時機
1、對象作爲參數,調用構造函數
//淺拷貝中的例子加入如下代碼
bool SetA(A a)
{
return true;
}
//void main()
SetA(a);
//彙編代碼
53: A b = a;
004012CA lea eax,[ebp-4] //a的指針
004012CD push eax
004012CE lea ecx,[ebp-8] //b的指針
004012D1 call @ILT+60(A::A) (00401041)
54: b.Output();
004012D6 lea ecx,[ebp-8]
004012D9 call @ILT+15(A::Output) (00401014)
55: SetA(a);
004012DE push ecx
004012DF mov ecx,esp //當前棧已經開闢了臨時對象空間,相當於b的指針
004012E1 lea edx,[ebp-4]
004012E4 push edx //a的指針
004012E5 call @ILT+60(A::A) (00401041)
004012EA call @ILT+10(SetA) (0040100f) //已經拷貝了到了ecx,所以就直接調用SetA(),此時esp就是臨時對象的指針
004012EF add esp,4 //esp+4 還是指向臨時對象
2、返回一個對象 CExample GetExpFun()
{
return g_objExp;
}
objExp2 = GetExpFunc();
004013E4 lea ecx,[ebp-40h] //返回的臨時對象空間是進入main函數的時候,提前分配好的。
004013E7 push ecx //先將對象壓棧
004013E8 call @ILT+25(GetExpFun) //調用函數
【點評】 返回對象時,也是在當前棧分配了臨時空間,會調用在函數中,調用拷貝構造函數,來賦值給臨時空間。相當於一箇中轉戰,先拷貝構造函數賦值給臨時空間,再用它。
參考:1、C++拷貝構造函數(深拷貝、淺拷貝)
4、拷貝構造函數