Nice shot. For better code management and reusability you could remove the delete from the if (pkOldGrid) check and put it into the override method CGrid::CGrid(CGrid * pkGrid, int w, int h) : m_iWidth(w), m_iHeight(h) like this:
CGrid::CGrid(int w, int h) : m_iWidth(w), m_iHeight(h)
{
m_pGrid = new char[m_iWidth * m_iHeight];
memset(m_pGrid, 0, sizeof(char) * m_iWidth * m_iHeight);
}
CGrid::CGrid(CGrid * pkGrid, int w, int h) : m_iWidth(w), m_iHeight(h) //<- if you add delete pkGrid here you can call M2_NEW CGrid(CGrid*, width, height) and it will delete the old pointer of safebox function at the end of this method
{
m_pGrid = new char[m_iWidth * m_iHeight];
int iSize = std::MIN(w * h, pkGrid->m_iWidth * pkGrid->m_iHeight);
thecore_memcpy(m_pGrid, pkGrid->m_pGrid, sizeof(char) * iSize);
//here
delete pkGrid;
}