我正在研究一個大學專案,我們將在其中將一些 C 字串類實作為 Mystring。我正在研究多載賦值運算子,這是它的當前代碼:
Mystring& Mystring::operator=(const Mystring& orig)
{
if(this != &orig)
{
delete ptr_buffer;
len = orig.len;
buf_size = orig.buf_size;
ptr_buffer = orig.ptr_buffer;
}
return *this;
}
ptr_buffer,長度。和 buf_size 是 Mystring 類的三個私有變數。這是我要測驗的主要程式:
void check (const Mystring s, const string name)
{
cout << "checking " << name << endl;
cout << name << " contains " << s << endl;
cout << name << " capacity() is " << s.capacity() << endl;
cout << name << " length() is " << s.length() << endl;
cout << name << " size() is " << s.size() << endl;
cout << name << " max_size() is " << s.max_size() << endl << endl;
}
int main()
{
Mystring s1("Hi there!");
check(s1, "s1");
Mystring s2("Testing before assignment!");
check(s2, "s2");
s2 = s1;
check(s2, "s2");
return 0;
}
這是輸出:
checking s1
s1 contains Hi there!
s1 capacity() is 10
s1 length() is 9
s1 size() is 9
s1 max_size() is 1073741820
checking s2
s2 contains Testing before assignment!
s2 capacity() is 27
s2 length() is 26
s2 size() is 26
s2 max_size() is 1073741820
checking s2
s2 contains Hi there!
s2 capacity() is 10
s2 length() is 9
s2 size() is 9
s2 max_size() is 1073741820
free(): double free detected in tcache 2
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
如您所見,賦值確實可以設定所有成員變數,但是我得到了一個非零退出代碼和一個 free(): double free detected in tcache 2 錯誤。我做錯了什么,這個錯誤是什么意思?我已經確認退出代碼來自呼叫賦值,因為當我注釋掉 s2 = s1; 時,它以退出代碼 0 結束。
uj5u.com熱心網友回復:
在這個復制賦值運算子中
Mystring& Mystring::operator=(const Mystring& orig)
{
if(this != &orig)
{
delete ptr_buffer;
len = orig.len;
buf_size = orig.buf_size;
ptr_buffer = orig.ptr_buffer;
}
return *this;
}
至少有兩個問題。如果指標指向的字符陣列ptr_buffer是動態分配的,則必須使用運算子delete []而不是delete
delete [] ptr_buffer;
第二個問題是在這個賦值之后
ptr_buffer = orig.ptr_buffer;
兩個指標指向同一個動態分配的記憶體。
您需要分配一個新的擴展記憶體并將分配物件的字串復制到那里。
運算子至少可以通過以下方式定義
Mystring & Mystring::operator =( const Mystring &orig )
{
if(this != &orig)
{
if ( buf_size != orig.buf_size )
{
delete [] ptr_buffer;
ptr_buffer = new char[orig.buf_size];
buf_size = orig.buf_size;
}
len = orig.len;
strcpy( ptr_buffer, orig.ptr_buffer );
// or if the class does not store strings then
// memcpy( ptr_buffer, orig.ptr_buffer, len );
}
return *this;
}
uj5u.com熱心網友回復:
據推測,Mystring有一個解構式,如下所示:
Mystring::~Mystring() {
delete[] ptr_buffer;
}
因此,您不能只獲取ptr_bufferfrom 的所有權而orig不用其他東西替換它。這在移動分配中是可行的,但是由于您處于復制分配中,因此您必須保持orig原樣。
這意味著您必須將orig的資料復制到其中,并在必要時分配一個新資料:
Mystring& Mystring::operator=(const Mystring& orig)
{
if(this != &orig)
{
std::size_t min_buf_size = orig.len 1; // or perhaps orig.buf_size, it depends.
// no need to allocate a new buffer if the current one is big enough already.
if(buf_size < min_buf_size) {
delete[] ptr_buffer;
buf_size = min_buf_size;
ptr_buffer = new char[buf_size];
}
len = orig.len;
assert(buf_size >= len 1);
std::memcpy(ptr_buffer, orig.ptr_buffer, len 1);
}
return *this;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/331743.html
下一篇:讀取字符后無法輸入整數
