事情的经过是这样的,我在实现一个基于OpenCv的CImage类。我需要实现它的拷贝构造函数,因为我要把它push_back到vector里面去。我过去的一直做法是在赋值操作符中实现真正的操作,在拷贝构造函数中调用。但是在这里却出现了内存错误。
好歹我还写过几年程序,那我就开始了艰辛的调试。经过调试我发现,我的程序一直只进入拷贝构造函数,然后进去赋值操作符,在赋值操作符中我释放了对象原有的内存。错误就出现在了这里。按照我这种写法的理解,push_back是先用默认构造函数构造对象加入vector,然后再用原有拷贝构造函数初始化内容,或者说用赋值操作符初始化内容。
事实上,完全不是这样的。 push_back直接添加新的内存,然后对这块新的内存用拷贝构造函数初始化而已。 既然这样的话,拷贝构造函数是不能够直接调用赋值操作符的。应该再重新写一个真正的赋值子函数,拷贝构造函数和赋值操作符都调用这个子函数。赋值操作符中多了一个先检查是否同一个对象,如果不是同一个则释放原有内存的过程而已。
具体的可以看,CImage的部分代码。
http://www.xpc-yx.com/2013/12/19/%e6%8b%b7%e8%b4%9d%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e7%9a%84%e7%90%86%e8%a7%a3%e9%94%99%e8%af%af/
好歹我还写过几年程序,那我就开始了艰辛的调试。经过调试我发现,我的程序一直只进入拷贝构造函数,然后进去赋值操作符,在赋值操作符中我释放了对象原有的内存。错误就出现在了这里。按照我这种写法的理解,push_back是先用默认构造函数构造对象加入vector,然后再用原有拷贝构造函数初始化内容,或者说用赋值操作符初始化内容。
事实上,完全不是这样的。 push_back直接添加新的内存,然后对这块新的内存用拷贝构造函数初始化而已。 既然这样的话,拷贝构造函数是不能够直接调用赋值操作符的。应该再重新写一个真正的赋值子函数,拷贝构造函数和赋值操作符都调用这个子函数。赋值操作符中多了一个先检查是否同一个对象,如果不是同一个则释放原有内存的过程而已。
具体的可以看,CImage的部分代码。
class CImage
{
public:
CImage();
~CImage();
CImage(const CImage& yxImage);
CImage& operator =(const CImage& yxImage);//深度拷贝
private:
void CopyData(const CImage& yxImage);
};
CImage::CImage(void)
{
m_pImg = NULL;
m_ppfData = NULL;
m_pfData = NULL;
}
CImage::CImage(const char* pcszName)
{
m_pImg = NULL;
m_ppfData = NULL;
m_pfData = NULL;
Load(pcszName);
}
CImage::~CImage(void)
{
UnInit();
}
void CImage::CopyData(const CImage& yxImage)
{
m_pImg = cvCloneImage(yxImage.m_pImg);
m_nRows = m_pImg->height;
m_nCols = m_pImg->width * m_pImg->nChannels;
int nLineSize = m_nCols * sizeof(double);
m_ppfData = new double*[m_nRows];
m_pfData = new double[m_nRows * m_nCols];
for (int i = 0; i < m_pImg->height; ++i)
{
m_ppfData[i] = &m_pfData[i * m_nCols];
memcpy(m_ppfData[i], yxImage[i], nLineSize);
}
}
CImage::CImage(const CImage& yxImage)//复制构造函数
{
//*this = yxImage;//不能用=来实现,否则在push_back时候会出现内存错误,因为vector不调用默认构造函数
//而是先添加对象的内存,再用复制构造函数初始化数据
CopyData(yxImage);
}
CImage& CImage::operator=(const CImage& yxImage)
{
if (this == &yxImage)
{
return *this;
}
UnInit();
CopyData(yxImage);
return *this;
}
http://www.xpc-yx.com/2013/12/19/%e6%8b%b7%e8%b4%9d%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e7%9a%84%e7%90%86%e8%a7%a3%e9%94%99%e8%af%af/