拷贝分为复制数据、复制内存
当我们想要把一个对象或一段数据从一个地方复制到另一个地方时,我们会有两个副本。
大部分情况下我们想复制对象,并以某种方式修改他们。
如果我们只是想读取,我们可以避免复制不必要的复制,复制是需要时间的
不必要的复制是不好的,会浪费性能
赋值操作
int a=2;
int b=a;
b=3;
a,b是两个不同的内存地址
/+程序执行后a=2;b=3
///指针赋值操作
struct Vector2
{
float x,y;
};
int main{
Vector2 *a=new Vector2();
///赋值指针地址
Vector2 *b=a;
b->x=2;
//a和b他们指向同一个内存地址。改变b的值a的值也会改变
}
一、深拷贝与浅拷贝区别
浅拷贝:简单的复制拷贝操作
深拷贝:在堆区重新申请内存空间,进行拷贝操作
二、拷贝构造函数
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量。
当出现类的等号赋值时,会调用拷贝函数
在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝构造函数-----即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。
但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。
所以这时必须采用深拷贝
深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。
简而言之,当数据成员中有指针时,必须要用深拷贝
第一种:赋值测试
class String
{
private:
char *m_buffer;
int m_Size;
public:
String(const char *string)
{
m_Size=strlen(string);
m_buffer=new char[m_Size+1];
memcpy(m_buffer,string,m_Size);
m_buffer[m_Size]=0;///手动添加字符串空终止符号
}
friend std::ostream &operator<<(std::ostream& stream,const String & string); //重载符号<<
};
~String()
{
delete[] m_buffer;
}
std::ostream &operator<<(std::ostream& stream,const String & string)
{
stream<<string.m_buffer;
return stream;
}
int main()
{
String string ="hello";
std::cout<<string<<std::endl;
//第一种赋值测试----复制指针
//赋值时会m_buffer是浅拷贝赋值,两个对象的m_buffer变量指向同一个地址
//当执行到作用域尽头时,这两个Sting对象都被销毁了,析构函数会被调用,然后执行delete[] m_buffer两次
String string="hello";
String string2=string;
std::cout<<string<<std::endl;
//
}
第二种:拷贝构造函数
class String
{
..........
public:
String(const String &other)
:m_Size(other.m_Size)
{
m_Buffer=new char[m_Size+1];
memcpy(m_buffer,other.m_buffer,m_Size+1);
}
};
int main()
{
//第二种测试----拷贝构造函数
//赋值时会调用拷贝构造函数,执行的是深拷贝,两个对象的String指向不同的内存地址
//更改string2的值,string不会改变
String string="hello";
String string2=string;
std::cout<<string<<std::endl;
//
}
第三种:定义拷贝函数
class String
{
...........
public:
void copy(const String &surStr)
{
if(this == surStr) //判断是否值同一个示例
return *this;
m_Size=surStr.m_Size;
m_buffer=new char[m_Size+1];
memcpy(m_buffer,surStr.m_buffer,m_Size=1);
}
}
int main()
{
//第三种测试----定义拷贝函数
//赋值时会调用拷贝函数,执行的是深拷贝,两个对象的m_buffer变量指针指向不同的内存地址
//更改string2的值,string不会改变
String string="hello";
String string2="Mello";
string2.copy(string);只改变值不改变指向
std::cout<<string<<std::endl;
//
}