侯捷c++課程 string類 筆記
class with pointer members
由於字串的長度是不確度的,所以使用陣列來存放字串,不好確定陣列大小
因此選擇使用char* 動態分配記憶體的方式來儲存
Big three 3個特殊函式
字串string類的資料成員只有一個char* 指標,通過動態分配記憶體指向字串
帶有指標的類有三個特殊函式 解構函式 複製建構函式 operator =
不能使用編譯器自動生成的operator =和複製建構函式,這些函式是直接的bit by bit 的指標賦值
會造成記憶體洩漏,即內容還在那裡,沒有被回收,但沒有指標指向這裡
同時會形成兩個指標指向同一塊記憶體區域,當一個指標delete後,另外一個也會受影響(alias)
複製建構函式和建構函式
首先獲取引數的字元長度,由於strlen返回的長度不包括結尾的'\0',所以要分配的記憶體空間要strlen(cstr)+1
在常規的建構函式中,即使指標引數為空指標,也要分配一個char的記憶體空間,內容為'\0'
inline String::String(const char* cstr = 0) { if (cstr) { m_data = new char[strlen(cstr) + 1]; strcpy(m_data, cstr); } else { m_data = new char[1]; *m_data = '\0'; } }
呼叫strcpy複製,自動複製結尾的'\0'
inline
String::String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
解構函式
當string類的例項物件的作用域結束後,os會收回其所佔用的記憶體空間
但string類的資料只有一個指標,這個指標所指向的內容是不會自動回收的,所以要在解構函式中手動delete
inline
String::~String()
{
delete[] m_data;
}
operator =
實現和複製建構函式類似,但是要先清空自身內容,再進行賦值
要判定自我賦值的情況,如果不判斷,將直接清空自身的內容,指標成為野指標,會發生undefined behavior
inline
String& String::operator =(const String& str)
{
if (this == &str)
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
stack heap
在函式function body內宣告的變數,記憶體來自於stack
heap是os提供的一塊global記憶體空間,可通過new進行動態分配記憶體
stack object在作用域結束後被自動清理 而heap object仍然存在
static
在變數宣告前加static關鍵字,即為static object,其在作用域結束後仍然存在,直到整個程式結束
global object也可看作一種static object,作用域是整個程式
new delete
new被編譯器轉化為三個步驟:
1.呼叫malloc分配記憶體
2.static_cast型別轉換
3.呼叫建構函式
delete為兩個步驟:
1.呼叫解構函式
2.呼叫free釋放記憶體
array new 一定要搭配 array delete
delete 和 delete[] 都會將其所指的記憶體塊全部釋放
區別在於delete[]會對陣列內的每一個元素呼叫解構函式 而delete只對第一個元素呼叫
如果陣列元素為帶有指標成員的類,使用delete會造成memory leak