深浅拷贝
概念
深浅拷贝问题是在类的默认构造函数中常常会出现的问题,一般都是发生在带有指针的类中,凡是一个带有指针的类需要让指针指向开辟在堆上的空间时就需要注意这个问题了。
浅拷贝:又称值拷贝,只是单纯的将对象中的成员变量的值拷贝到另一个对象的成员变量中。
深拷贝:当要拷贝一个指针并且指针指向的一块新开辟出的空间的时候,想要拷贝出另一个也指向一块新开辟出的空间的指针,这是浅拷贝做不到的,这时就需要用到深拷贝。
浅拷贝
拿Complex
类举例子
class Complex
{
// 默认生成的拷贝构造和赋值运算符重载都是浅拷贝
// 这里显式的写出来方便理解
// 拷贝构造
Complex(const Complex& tmp)
{
_real = tmp._real;
_img = tmp._img;
}
// 赋值运算符重载
Complex& operator= (const Complex& tmp)
{
if (this != &tmp)
{
_real = tmp._real;
_img = tmp._img;
}
return *this;
}
private:
int _real;
int _img;
};
深拷贝
带指针的类拿string
类举例子
class string
{
public:
// 拷贝构造
string(const string& str)
{
_data = str._data;// 单纯的值拷贝,这就是浅拷贝,也是默认生成的函数
}
// 赋值运算符重载
string& operator= (const string& str)
{
if (this != &str)// 确认str不是*this
{
_data = str._data;// 单纯的值拷贝,这也是浅拷贝,也是默认生成的函数
}
return *this;
}
// 下面是不是深浅拷贝的重点
// 构造函数
string(const char* str = ""):// 缺省值参数为空字符串,千万不要写成0
_data(new char[strlen(str) + 1])// 开辟新空间
{
strcpy(_data, str);// 拷贝
}
// 析构函数
~string()
{
delete[] _data;// 释放在堆上new出的空间
}
private:
char* _data;
};
既然默认生成的函数不能开辟空间,那就在拷贝构造和赋值运算符重载的内手动的开辟空间。
class string
{
public:
// 拷贝构造
string(const string& str):
_data(new char [strlen(str._data) + 1])// 开辟新空间
{
strcpy(_data, str._data);// 拷贝
}
// 赋值运算符重载
string& operator= (const string& str)
{
if (this != &str)// 确认str不是*this
{
delete[] _data;// 销毁原有空间
_data = new char[strlen(str._data) + 1];// 开辟新的空间
strcpy(_data, str._data);// 拷贝
}
return *this;
}
// 下面是不是深浅拷贝的重点
// 构造函数
string(const char* str = ""):// 缺省值参数为空字符串,千万不要写成0
_data(new char[strlen(str) + 1])// 开辟新空间
{
strcpy(_data, str);// 拷贝
}
// 析构函数
~string()
{
delete[] _data;// 释放在堆上new出的空间
}
private:
char* _data;
};
string简化版的代码演示
#include <iostream>
#include <cstring>
namespace zhy// 防止和std中的string冲突,我使用我的名字的命名空间
{
class string
{
public:
// 构造函数
string(const char* str = ""):// 缺省值参数为空字符串,千万不要写成0
_data(new char[strlen(str) + 1])// 开辟新空间
{
strcpy(_data, str);// 拷贝
}
// 拷贝构造
string(const string& str):
_data(new char [strlen(str._data) + 1])// 开辟新空间
{
strcpy(_data, str._data);// 拷贝
}
// 赋值运算符重载
string& operator= (const string& str)
{
if (this != &str)// 确认str不是*this
{
delete[] _data;// 销毁原有空间
_data = new char[strlen(str._data) + 1];// 开辟新的空间
strcpy(_data, str._data);// 拷贝
}
return *this;
}
// 析构函数
~string()
{
delete[] _data;// 释放在堆上new出的空间
}
private:
char* _data;
};
}
int main()
{
zhy::string str1("hello world");// 构造函数
zhy::string str2(str1);// 拷贝构造
zhy::string str3;// 构造函数(初始化为空字符串)
str3 = str2;// 赋值运算符重载
return 0;
}