C++——三大函数拷贝构造、拷贝复制、析构
以String类为例子,介绍三大函数的实现和原理,自己写类的时候可以参考String的这三个函数的流程和要点来写。
String s1();
String s2("hello"); //构造函数
String s3(s1); //拷贝构造
s3 = s2; //赋值操作,拷贝赋值
两个拷贝会有不同对应的函数操作,这两个函数如果没有写,编译器会默认给一个,实现就是默认的全部一个一个拷贝赋值过去。
但是,如果类中有指针,拷贝指针是没有意义的,可能会出错,这种情况得自己写。
构造函数和析构函数:
class String
{
public:
String(const char* cstr = 0):
String(const String& str):
String& operator=(const String& str):
~String():
char* get_c_str() const { return m_data; } //inline 函数,不改变值用const
private:
char* m_data; //定义成一个指针,可以有更好的发展空间,因为不确定将来的字符串到底有多长。
}
//构造函数
inline String::String(const char* sctr = 0)
{
if(cstr) {
m_data = newchar(strlen(cstr) + 1);
strcpy(m_data, cstr);
} else {
m_data = newchar[1];
*m_data ='\0';
}
}
//析构函数
inline String::~String()
{
delete[] m_data;
}
拷贝构造函数
如果有指针的不实现拷贝构造和拷贝赋值函数:
String a(“Hello”);
String a(“World”);
b = a;
没有拷贝构造函数,这样直接把a的指针直接拷贝过去,然后a也指向了b,从而Hello的地址就成了没人用的内存泄露memory leak,b有两个指向alias,有危险。这种叫作浅拷贝。
对应深拷贝,是创建一个蓝本空间将原来的之拷贝过去,这个就是拷贝构造函数。
//拷贝构造函数
inline String::String(const String& str)
{
m_data = new char[strlen(str.m_data)+1]
strcpy(m_data, str.m_data);
}
拷贝赋值函数
拷贝赋值操作过程:
1. 将原来的空间清空;
2. 分配一个和拷贝的对象的一样大的空间;
3. 将内容拷贝过去。
自己赋值给自己的情况:上面的String s3(s1);
如果内有自我赋值,经过上面的三个步骤,可能直接将原来的内容清空了,成为空的了。
//拷贝赋值函数
inline String& String::operator=(const String& str)
{
if(this == &str) //检测是不是自我赋值,继承或指针名称发生变化
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data)+1];
strcpy(m_data, str.m_data);
return *this;
}