c++的建構函式和析構方面(拷貝建構函式)

來源:互聯網
上載者:User

標頭檔
class  student
{
public:
 student(char*);
 ~student();
 student(const student &);
 char* name;
 static int num;
};

 main.cpp檔案

int  student::num=0;

student::student(char* myname)

{

num++;

int len=strlen(myname);

name=new char[len+1];

strcpy(name,myname);

cout<<name<<":建立,剩餘個數:"<<num<<endl;

}

student::~student()

{

num--;

cout<<name<<":銷毀,剩餘個數:"<<num<<endl;

delete [] name;

}

void fun(student  funs)

{

cout<<funs.name<<"被調用"<<endl;

}
void main()

{

student stu1("student1");//--------------1

student stu2("student2");//--------------2

student stu3("student3");//--------------3

 

fun(stu2);//--------------4

student stu4=stu3;//--------------5

student stu5("student5");//--------------6

stu5=stu1;//--------------7

}

1,2,3都很正常,到4的時候,實參為類值對象,傳遞過程是一個拷貝建構函式,funs在fun方法結束後會調用解構函式,而運行到5的時候,這是一個通過拷貝建構函式執行個體化類,這個過程不會調用構造方法和解構函式的,因為我們要瞭解拷貝建構函式是如何寫的,如下
student(const student & c)

{

name=c.name;

}

所以5就相當於 student stu4(stu3)

到7的時候只是賦值,不是通過拷貝建構函式執行個體化類,因為stu5已經在6的時候執行個體化了

這個代碼在VC 6.0中啟動並執行時候,神奇般的出錯了,第一個錯誤出在main函數結束後,一個個析構,堆棧的析構順序是先進後出,先析構stu5,再析構stu4,再析構stu3,就在析構stu3的時候出錯了。如下


為什麼會出錯,此時研究後發現是因為在5這個位置調用了拷貝建構函式來構造stu4類對象,根據拷貝建構函式的原型(下是原型)
student(const student & c)

{

name=c.name;

}

我發現name=c.name,對於5來說就是stu4.name=stu3.name;name是一個指標,這是一個指標賦值,即stu4的name指標指向了stu3的那麼指標指向的位置。那麼問題迎刃而解了,即在析構stu4的時候(因為堆棧析構順序先析構晚壓入棧的),delete [] name了,就是告訴電腦,name這塊記憶體被釋放了,不被任何東西指向(不和任何東西有關係),於是再去析構stu3的時候,出問題了。。你已經和這塊地址沒有關係了,憑什麼讓你delete。而且也沒必要delete了,但是如果你知道這塊空間地址,並通過地址直接存取這塊空間還是能訪問到name的值的,因為值並沒有被刪除,修改代碼後,你會更加明白問題在哪裡,在5和6之間加上一句:cout<<"stu3的name指向地址:"<<(int *)stu3.name<<"\t"<<"stu4的name指向地址:"<<(int *)stu4.name<<endl;
輸出(您可以不要直接cout<<"stu3的name指向地址:"<<&stu3.name<<"\t"<<"stu4的name指向地址:"<<&stu4.name<<endl;這樣來訪問,這是擷取該指標在堆棧中的地址,而不是內容在堆中儲存的地址)

要解決這個問題。。看樣子只有重寫拷貝建構函式了(下面是重構拷貝建構函式)

student::student(const student& tempstu)

{

int len=strlen(tempstu.name);

name=new char[len+1];

strcpy(name,tempstu.name);

}
以為一切問題解決,可是啟動並執行時候

很明顯這是在析構1的時候,即析構stu1的時候,發現第7句stu5=stu1;這隻是一個賦值過程,因為stu5對象在第6句就構造了,賦值的過程的話,即依然是stu5.name=stu1.name,然後問題原因道理同上。這就是所謂的淺複製的過程,這也是淺複製容易導致的問題(大家可以去研究淺複製和深複製)

至於結構中的最後 的剩餘個數為什麼編程-2了,(其實這個例子模仿c++ primer),主要是因為位置4調用了fun(stu2);-這個調用,傳遞了一個實參為stu2的類對象,在傳遞過程類似
student  funs=stu2;這個funs對象在fun方法返回時會銷毀,銷毀就會調用解構函式num--,而且在第5位置處,是通過student stu4=stu3這種拷貝建構函式來執行個體化stu4,在重寫的拷貝建構函式中,我們並沒有讓num++,而析構他的時候卻有num--了,這就是為什麼最後num不會迴歸至初始0,而是-2

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.