(1)浅拷贝
比如定义一个Book类,
执行
Book bookA;
Book bookB(bookA)或Book bookB = bookA
如果没有实现拷贝构造函数,将会使用系统默认的拷贝构造函数,而系统默认生成的拷贝构造函数属于浅拷贝,当存在指针时,拷贝的仅仅是指针的地址,拷贝后,两个对象指向的内存地址相同,当其中一个对象销毁执行析构函数时,另外的一个对象的指针变成了迷途指针(野指针,指针悬挂),将会导致同一块内存被释放2次。
(2)而深拷贝,对于存在指针的情况时,拷贝的将是指针指向的内容,而不是单纯的赋值指针的地址,经深拷贝后的指针是指向两个不同地址的指针(各自有各自的堆内存)。
浅拷贝的例子,代码实例
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int a=0;
class Book
{
public:
Book()
{
m_pchBookname = NULL;
}
Book(const char *str)
{
if(NULL != str)
{
int len = strlen(str) + 1;
m_pchBookname = new char[len];
if(NULL != m_pchBookname)
{
memset(m_pchBookname , 0, len);
strncpy(m_pchBookname, str, len -1);
}
}
else
{
m_pchBookname = NULL;
}
}
Book(const Book & otherBook)//浅拷贝
{
m_pchBookname = otherBook.m_pchBookname;
}
~Book()
{
a++;
std::cout<<"~Book " <<std::endl;
printf("\nm_pchBookname=%p a = %d\n",m_pchBookname,a);
if(NULL != m_pchBookname)
{
delete m_pchBookname;
}
m_pchBookname = NULL;
}
void print()
{
std::cout<<m_pchBookname<<std::endl;
}
private:
char *m_pchBookname;
};
int main()
{
Book bookA("BookA Name");
Book bookB(bookA);
//bookB.~Book();
return 0;
}
看见没有 浅拷贝的后果,double free
改进后,即改成深拷贝
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int a=0;
class Book
{
public:
Book()
{
m_pchBookname = NULL;
}
Book(const char *str)
{
if(NULL != str)
{
int len = strlen(str) + 1;
m_pchBookname = new char[len];
if(NULL != m_pchBookname)
{
memset(m_pchBookname , 0, len);
strncpy(m_pchBookname, str, len -1);
}
}
else
{
m_pchBookname = NULL;
}
}
Book(const Book & otherBook)//深拷贝
{
if(NULL != otherBook.m_pchBookname)
{
int len = strlen(otherBook.m_pchBookname) + 1;
m_pchBookname = new char[len];
if(NULL != m_pchBookname)
{
memset(m_pchBookname , 0, len);
strncpy(m_pchBookname,otherBook.m_pchBookname, len -1);
}
}
else
{
m_pchBookname = NULL;
}
}
~Book()
{
a++;
std::cout<<"~Book " <<std::endl;
printf("\nm_pchBookname=%p a = %d\n",m_pchBookname,a);
if(NULL != m_pchBookname)
{
delete m_pchBookname;
}
m_pchBookname = NULL;
}
void print()
{
std::cout<<m_pchBookname<<std::endl;
}
private:
char *m_pchBookname;
};
int main()
{
Book bookA("BookA Name");
Book bookB(bookA);
//bookB.~Book();
return 0;
}
通过声明拷贝构造函数和重载符=拷贝为私有的,禁止拷贝。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int a=0;
class Book
{
public:
Book()
{
m_pchBookname = NULL;
}
Book(const char *str)
{
if(NULL != str)
{
int len = strlen(str) + 1;
m_pchBookname = new char[len];
if(NULL != m_pchBookname)
{
memset(m_pchBookname , 0, len);
strncpy(m_pchBookname, str, len -1);
}
}
else
{
m_pchBookname = NULL;
}
}
~Book()
{
a++;
std::cout<<"~Book " <<std::endl;
printf("\nm_pchBookname=%p a = %d\n",m_pchBookname,a);
if(NULL != m_pchBookname)
{
delete m_pchBookname;
}
m_pchBookname = NULL;
}
void print()
{
std::cout<<m_pchBookname<<std::endl;
}
private:
Book(const Book & otherBook)
{
}
Book & operator = (const Book & otherBook)
{
return *this;
}
char *m_pchBookname;
};
int main()
{
Book bookA("BookA Name");
Book bookB(bookA);
Book bookC = bookA;
//bookB.~Book();
return 0;
}