以下這段程式有錯誤,是關於沒有複製建構函式的錯誤,下面我們將解開這段程式錯誤之謎:
#include <string.h>#include <vector>#include <iostream>using namespace std;int i=0;int j=0;class CDemo{ public: CDemo():str(NULL){cout<<"constructor_"<<i++<<endl;}; //注釋掉下面這段複製建構函式 //CDemo(const CDemo &cd){cout<<"constructor_"<<i++<<endl;this->str=new char[strlen(cd.str)+1];strcpy(str,cd.str);}; ~CDemo(){cout<<"destrcutor_"<<j++<<endl;if(str) delete []str;}; char *str;};int main(){ CDemo d1; d1.str=new char[32]; strcpy(d1.str,"hello_a_world"); vector<CDemo> *a1=new vector<CDemo>(); a1->push_back(d1);//×××××××××關鍵語句 delete a1;}
原始碼中已經標出了關鍵語句,這段語句中主要函數是屬於vector的push_back,下面看看push_back源碼:
void push_back(const T &x){ if(finish!=end_of_storage) { construct(finish,x); ++finish; } else//如果備用空間不足 { insert_aux(end(),x); }}
constuct函數的原型如下:
template<class T1,class T2>inline void construct(T1 *p,const T2&value){ new (p)T1(value);}
好了,上一篇文章(定位new運算式)已經列出來了,這裡是一個定位new運算式,那麼演算法深入到這一步,我們到底是需要什麼呢?首先new(p)T1(value)中,p是個指標,或者說是個迭代器,這個指標所指的類型是T1,那麼在本例中T1是什麼呢?是CDemo;T2的類型是什麼呢?也是CDemo,好了,new是要初始化這片記憶體的,應該選用哪個建構函式呢,很顯然是一個像下面這樣的複製建構函式了:
CDemo(const CDemo &cd){};
但是,來源程式裡面是沒有這段函數的,所以會報錯。因此只要在原始碼把注釋符去掉一切就都OK了。