首先来介绍一下浅拷贝:
所谓浅拷贝就是将一个对象中的内容原封不动发拷贝到另一个对象之中去,从字节上直接拷贝过去,这样说可能有点绕,简单来说在拷贝过程中涉及到动态内存管理,没有为其申请空间,而是将原空间的位置给了过去,可以认为共用一块空间。
浅拷贝的危害:当对象要销毁时,同一份资源被销毁多次导致代码崩溃。
解决方法:使用深拷贝,让每一个对象都独立拥有自己的资源,即发生拷贝构造或赋值时,重新申请一块空间将资源拷贝过去。
接下来实现String类,String类中涉及到资源的管理问题,所以必须显示定义拷贝构造函数和赋值运算符函数,在显示定义时注意不要发生浅拷贝和内存泄漏问题。
#include<iostream>
#include<string>
using namespace std;
class String {
public:
String(const char* str="") {
if (str == nullptr) {
str = "";//避免使用nullptr定义对象
}
_str = new char[strlen(str) + 1];
strcpy_s(_str, strlen(str) + 1, str);
}
~String()
{
if (_str != nullptr) {
delete[] _str;//回收空间
_str = nullptr;
}
}
String(const String& s) {
_str = new char[strlen(s._str) + 1];//避免浅拷贝,出现申请空间
strcpy_s(_str, strlen(s._str) + 1, s._str);
}
String& operator= (const String& s){
if (this != &s) {
char* temp;
temp = new char[strlen(s._str) + 1];//申请一份零时空间作为媒介
strcpy_s(temp, strlen(s._str) + 1, s._str);
swap(temp, _str);//零时空间与类中存储字符串位置交换
delete[] temp;
temp = nullptr;//回收零时空间
}
return *this;
}
private:
char* _str;
};
int main() {
String s1("hello");
String s2(nullptr);
String s3(s1);
String s4 ;
s4 = s1;
return 0;
}
以上是通过vs2019进行String实现,实现结果如下:
可以发现:s1,s2,s3,s4每一个对象都有一块属于自己的空间,避免了浅拷贝以及内存泄漏的问题。