深浅拷贝
浅拷贝存在的问题:如果类不提供拷贝构造和拷贝赋值编译器将提供默认的拷贝构造和拷贝赋值,而默认的拷贝构造和拷贝赋值函数,对于指针型成员变量都是只复制地址,而并不是复制地址指向的数据,这将导致浅拷贝问题。为了获得完整意义上的对象副本,必须自己定义拷贝构造和拷贝赋值,针对指针型成员变量做深拷贝
拷贝构造与拷贝赋值
1.相对于拷贝构造,拷贝赋值需要做更多的工作
避免自赋值
分配新资源
拷贝新内容
释放旧资源
返回自引用
2.无论是拷贝构造还是拷贝赋值,其默认实现对任何类型的指针成员都是简单地复制地址,因此应尽量避免使用指针型成员变量
3.出于具体原因的考虑,确实无法实现完整意义上的拷贝构造和拷贝赋值,可将它们私有化,以防误用
4.如果为一个类提供了自定义的拷贝构造函数,就没有理由不提供相同逻辑的拷贝赋值运算符函数
#include <iostream>
#include <cstring>
using namespace std;
class String
{
public:
String(const char* psz=""):m_psz(new char[strlen(psz)+1])
{
strcpy(m_psz,psz);
}
~String(/*String* this*/)
{
delete[] this->m_psz;
this->m_psz=NULL;
}
#if 0
String(const String& that)//默认拷贝构造函数,只复制了地址,没有复制地址指向的数据
{
}
#endif
String(const String& that):m_psz(new char[strlen(that.m_psz)+1])//复制数据,不复制地址(深拷贝)
{
strcpy(m_psz,that.m_psz);
}
#if 0
String& operator=(const String& that)//浅拷贝
{
m_psz=that.m_psz;
return *this;
}
#endif
String& operator=(const String& that)//深拷贝赋值函数
{
if(this != &that)//防止自赋值
{
delete[] this->m_psz;
this->m_psz=new char[strlen(that.m_psz)+1];
strcpy(this->m_psz,that.m_psz);
}
return *this;
}
char*c_str() {return m_psz;}
private:
char* m_psz;//指针成员
};
int main()
{
String s1("hello");
cout << "s1:"<<s1.c_str()<<",s1维护的堆内存首地址:" << (void*)s1.c_str() << endl;
String s2=s1;
cout << "s2:"<<s2.c_str()<<",s2维护的堆内存首地址:" << (void*)s2.c_str() << endl;
String s3;
s3=s2;
cout << "s3:"<<s3.c_str()<<",s3维护的堆内存首地址:" << (void*)s3.c_str() << endl;
return 0;
}
运行结果