初探浅拷贝
前言:什么是浅拷贝?
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制
- 这是一段浅拷贝的代码(我们可以看看其中的问题)
#include<iostream>
using namespace std;
class String
{
public:
String( char *str="")
{
cout << "create String Obj:" <<this<< endl;
m_data = (char*)malloc(strlen(str) + 1);
strcpy(m_data, str);
}
String(const String &s)
{
m_data = s.m_data;//将s.m_data指向的空间地址赋值给m_data指针
}
~String()
{
cout << "free String Obj:" << this << endl;
free(m_data);
m_data = nullptr;
}
private:
char *m_data;
};
void main()
{
String s("zhb");
String s1(s);
}
m_data=s.m_data
这条语句实行的就是浅拷贝,打开监视器可以看到:
当我们进行赋值语句时:例如:
void main()
{
String s("zhb");
String s1;
s1 = s;//赋值语句
}
**程序会发生崩溃!究其原因我们可以看一下赋值语句的原型:
String operator=(const String &s)
{
if (this != &s)
{
m_data = s.m_data;
}
return *this;
}
这里只是将s.m_data指向的空间地址赋值给m_data,因为浅拷贝造成了两个对象的成员指向了同一块空间,所以在程序执行之后会发生崩溃,在这种情况下为了避免程序崩溃我们可以将程序改造。
#include<iostream>
using namespace std;
class String
{
public:
String( char *str="")
{
cout << "create String Obj:" <<this<< endl;
m_data = (char*)malloc(strlen(str) + 1);
strcpy(m_data, str);
}
/*
String(const String &s)
{
m_data = s.m_data;//将s.m_data指向的空间地址赋值给m_data指针
}
*/
String(const String &s)
{
m_data = (char*)malloc(strlen(s.m_data) + 1);
strcpy(m_data, s.m_data);
}
String operator=(const String &s)
{
if (this != &s)
{
free(m_data);
m_data = (char*)malloc(strlen(s.m_data) + 1);
strcpy(m_data, s.m_data);
}
return *this;
}
~String()
{
cout << "free String Obj:" << this << endl;
free(m_data);
m_data = nullptr;
}
private:
char *m_data;
};
void main()
{
String s("zhb");
String s1;
s1=s;
}
在这种情况下我们可能觉得深拷贝会比浅拷贝好一点,至少能避免同一块空间被释放两次,但事实并非如此。
我们可以假设一种情形:
对象s与对象s1的私有成员m_data现在指向的是同一片空间,此时如果对象s1想更改m_data管理空间的值,那么s所管理空间的值也就发生了改变,这对于s来说显然是不公平的,下一篇博客我将会分享深浅拷贝在另一种情况下的使用