1. 程式人生 > >拷貝建構函式和賦值函式的區別

拷貝建構函式和賦值函式的區別

// 結論:拷貝建構函式在對還沒存在的物件賦值時會呼叫; 賦值函式在對已經存在的物件賦值會呼叫;賦值函式初始化前需要清理堆資源等,拷貝構造不需要。結構體有堆資源等資源要拷貝時,接的寫賦值函式和拷貝建構函式,否則會得到不確定的值。

// 測試程式碼可直接執行

// ConstructorTest.h 檔案

class ConstructorTest
{
public:
ConstructorTest();
~ConstructorTest();
ConstructorTest(char *pName);
ConstructorTest(const ConstructorTest &otherObj);  //A objA = ObjB; // 呼叫的是拷貝建構函式(無論類還是結構體).
ConstructorTest& operator =(const ConstructorTest &otherObj);  //  A objC; objC = objA;// 呼叫的是賦值函式(無論類還是結構體).
void UseConstructorTest(ConstructorTest testObj);  // 函式引數中傳遞物件值或者函式返回物件值時,呼叫的都是拷貝建構函式。
ConstructorTest GetConstructorTest(ConstructorTest &testObj);
void PrintContent();
private:
char* m_pName;

};

// ConstructorTest.cpp檔案

#include <string.h>
#include <iostream>
using namespace std;
#include "classCharacter.h"


struct tagName
{
char* m_pName;
tagName()
{
m_pName = NULL;
}

tagName& operator =(const tagName& b)
{
if(m_pName != NULL)
{
delete m_pName;
}
m_pName = new char[strlen(b.m_pName) + 1];
strcpy(m_pName, b.m_pName);
cout<<"tagName operator = call !"<<endl;
return (*this);
}


tagName(const tagName &b)
{
m_pName = new char[strlen(b.m_pName) + 1];
strcpy(m_pName, b.m_pName);
cout<<"tagName Deep Constructor call !"<<endl;
}
};

ConstructorTest::ConstructorTest()
{
m_pName = NULL;
}


ConstructorTest::~ConstructorTest()
{
if(m_pName != NULL)
{
delete []m_pName;
}
}

ConstructorTest::ConstructorTest(char *pName)
{
cout<<"ConstructorTest Constructor  Call!"<<endl;
m_pName = new char[strlen(pName) + 1];
strcpy(m_pName, pName);
}

ConstructorTest::ConstructorTest(const ConstructorTest &otherObj)
{
/*if(m_pName != NULL)
{
delete [] m_pName; // 宣告的時候賦值才會呼叫,故不用清理記憶體;如果清理會dump機
}*/


cout<<"ConstructorTest Deep Constructor Call!"<<endl;
m_pName = new char[strlen(otherObj.m_pName) + 1];
strcpy(m_pName, otherObj.m_pName);
}

ConstructorTest& ConstructorTest::operator =(const ConstructorTest &otherObj)
{
cout<<"ConstructorTest Assigment Constructor Call!"<<endl;

if(this == &otherObj)// 檢查自賦值
{
return (*this);
}
if(m_pName != NULL)
{
delete [] m_pName;
}
m_pName = new char[strlen(otherObj.m_pName) + 1];
strcpy(m_pName, otherObj.m_pName);


return (*this);
}

void ConstructorTest::UseConstructorTest(ConstructorTest testObj)
{
ConstructorTest *pTestObj = &testObj;
pTestObj->PrintContent();
}


ConstructorTest ConstructorTest::GetConstructorTest(ConstructorTest &testObj)
{
return testObj;
}

void ConstructorTest::PrintContent()
{
cout<<"The content is: "<<m_pName<<endl;
}

void main()
{
cout<<"-------------Class Contructor Test-------------"<<endl;
ConstructorTest Name1("Sandy Ou");
Name1.PrintContent();

ConstructorTest Name2 = Name1;
Name2.PrintContent();


ConstructorTest Name3;
Name3 = Name1;
Name3.PrintContent();

Name3.UseConstructorTest(Name2);
ConstructorTest Name4 = Name3.GetConstructorTest(Name2);
Name4.PrintContent();

cout<<"-------------struct Contructor Test-------------"<<endl;
tagName nameA;
nameA.m_pName = "JesseCen";
tagName nameB = nameA;
cout<<"tagName content is:"<<nameB.m_pName<<endl;

while(1);
}