您好,登錄后才能下訂單哦!
淺拷貝:以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.精簡深拷貝
1.傳址,在方法中重新定義一個對象接受被拷貝對象元素,然后交換臨時對象和需要拷貝對象的地址
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.淺拷貝+計數(相當于出門時,最后一個人才“關門”,進出門的人進行計數)
計數:定義一個成員_count,在普通構造函數中直接初始化為1,而進行拷貝構造時判斷被拷貝對象的成員_count++,而需要拷貝對象的成員_count是否為0,(如果為0,則需要拷貝對象成員_count++,如果>0,則則需要拷貝對象成員_count--),最后析構函數中對象_count成員為0時,調用delete
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];
}
};
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。