以下這段程序有錯誤,是關於沒有複製構造函數的錯誤,下面我們將解開這段程序錯誤之謎:
#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了。