拷贝构造函数的理解错误

事情的经过是这样的,我在实现一个基于OpenCv的CImage类。我需要实现它的拷贝构造函数,因为我要把它push_back到vector里面去。我过去的一直做法是在赋值操作符中实现真正的操作,在拷贝构造函数中调用。但是在这里却出现了内存错误。

好歹我还写过几年程序,那我就开始了艰辛的调试。经过调试我发现,我的程序一直只进入拷贝构造函数,然后进去赋值操作符,在赋值操作符中我释放了对象原有的内存。错误就出现在了这里。按照我这种写法的理解,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;
}