浅拷贝:以string类为例 当对一个已知对象进行拷贝时,编译系统会自动调用一种构造函数 —— 拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。默认拷贝构
当对一个已知对象进行拷贝时,编译系统会自动调用一种构造函数 —— 拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。默认拷贝构造属于浅拷贝,相当于两个指针变量指向了同一块地址空间,调用析构函数时,会delete两次,所以在第二次delete时会发生中断(无法寻址地址)
//浅拷贝
class string
{
private:
char* _str;
public:
string(char* str = "")//构造函数
{
if (nullptr == str)
{
str = "";
}
_str = new char[strlen(str) + 1];
strcpy(_str,str);
}
string(const string& s)//拷贝构造
:_str(s._str)
{
}
string operator =(string& s)//赋值构造
{
_str = s._str;
return *this;
}
~string()
{
if (_str)
{
delete _str;
_str = nullptr;
}
}
};
解决方案1.传统深拷贝
//缺点:需要多次开辟空间,代码冗余
//优点:可读性高
class string
{
private:
char* _str;
public:
string(char* str = "")
{
if (str == nullptr)
{
str = "";
}
_str = new char[strlen(str) + 1];
strcpy(_str,str);
}
string(const string& s)
:_str(new char[strlen(s._str)+1])
{
strcpy(_str,s._str);
}
string& operator=(string& s)
{
if (this != &s)
{
char* temp = new char[strlen(s._str) + 1];
strcpy(temp,s._str);
delete _str;
_str = temp;
}
return *this;
}
~string()
{
if (_str)
{
delete _str;
_str = nullptr;
}
}
};
解决方案2.
//优点:代码高效 缺点:可读性不高
class string
{
private:
char* _str;
public:
string(char* str="")
{
if (str == nullptr)
{
str = "";
}
_str = new char[strlen(str) + 1];
strcpy(_str,str);
}
string(const string& s)
:_str(nullptr)
{
string temp(s._str);
swap(_str,temp._str);
}
/*string& operator=(const string& s)
{
if (this != &s)
{
string temp = s._str;
swap(_str,temp._str);
}
return *this;
}*/
string& operator=(string s)//直接改变指向(传值:临时变量)
{
swap(_str,s._str);
return *this;
}
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
};
解决方案3.浅拷贝+计数
class string
{
private :
char* _str;
int* _count;
public :
string(char* str="")
: _count(new int(1))//调用普通构造:_count初始化为1
, _str(new char[strlen(str) + 1])
{
if (str == nullptr)
{
str = "";
}
strcpy(_str,str);
}
string(const string& s)
:_str(s._str)
, _count(s._count)
{
++(*_count);
}
string operator=(string& s)
{
if (this != &s)
{
if (0 == --(*_count))
{
delete[] _str;
delete _count;
_str = nullptr;
_count = nullptr;
}
_str = s._str;
_count = s._count;
++(*_count);
}
return *this;
}
~string()
{
if (_str&&0 == --(*_count))
{
delete[] _str;
delete _count;
_str = nullptr;
_count = nullptr;
}
}
char& operator[](size_t index)
{
if ((*_count) > 1)
{
string temp(_str);
this->swap(temp);
}
return _str[index];
}
void swap(string& s)
{
std::swap(_str,s._str);
std::swap(_count,s._count);
}
const char& operator[](size_t index)const
{
return _str[index];
}
};
