第二周主要學習的是 class with pointer member,通過以String Class的設計來學習
String類最后要實現(xiàn)如下功能
String s1 ();
String s2 ("hello");
String s3 (s1); // 拷貝構造
s3 = s2; // 拷貝賦值
編譯器會給每個類默認提供拷貝構造和拷貝賦值的函數(shù)书幕,通過一個byte一個byte的拷貝。而對于類中有指針的情況景用,需要自己來實現(xiàn)這兩個函數(shù)杨凑,避免和新產生的對象指向堆中內存的同一個地址
Big Three 三個特殊函數(shù)
class String {
public:
String(const char* cstr = 0); // 構造函數(shù)
String(const String& str); // 拷貝構造
String& operator=(const String& str); // 拷貝賦值
~String(); // 析構函數(shù)
char* get_c_str() const { return m_data; }
private:
char* m_data;
};
下面來看各個函數(shù)的實現(xiàn)
// 構造函數(shù)
inline String::String(const char *cstr) {
if (cstr) {
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
} else {
m_data = new char[1];
*m_data = '\0';
}
}
// 拷貝構造
inline String::String(const String &str) {
m_data = new char(strlen(str.m_data) + 1);
strcpy(m_data, str.m_data);
}
// 拷貝賦值
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;
}
// 析構函數(shù)
inline String::~String() {
delete[] m_data;
}
最后為了方便輸出String览徒,重載<<操作符
std::ostream& operator << (std::ostream &os, const String &str) {
os<<str.get_c_str();
return os;
}
堆突诬、棧 內存管理
{
Complex c1(1, 2); // 這種方式變量是創(chuàng)建在函數(shù)的棧上的
Complex* p = new Complex(3); // 創(chuàng)建一個復數(shù),初值是3睦袖,而值是創(chuàng)建在堆上的珊肃,動態(tài)獲得,需要手動釋放
}
stack object 的生命周期:只要離開作用域馅笙,就結束了伦乔。c1便是stack object,又稱為auto object董习,因為它會被『自動』清理
static local object的生命周期:如果在c1前加上static關鍵字烈和,則其在離開作用域后仍然存在,直到整個程序結束
global object 的生命周期:在任何大括號之外的地方聲明的皿淋,也可視為一種static object招刹,在整個程序結束后被清理
heap object 的生命周期:其生命在被delete時結束,如果忘記delete窝趣,將會造成memory leak疯暑,當作用域結束,指針所指向的heap object仍然存在哑舒,但指針的生命已經結束了
new: 先分配memory,再調用ctor
new 操作編譯器將會分解為3個動作缰儿,1. 分配內存 2. 對指針做類型轉換 3. 執(zhí)行構造函數(shù)
delete: 先調用dtor,再釋放memory
delete 操作編譯器將會分解為2個動作,1. 執(zhí)行dtor 2. 釋放內存
補充的知識點
- static
類中數(shù)據和函數(shù)前散址,均可添加static關鍵字
non static member function,編譯器會自動給一個this pointer宣赔,而static member function 是沒有的预麸,所以static member function 不能使用non static member data,只能處理static member data
static member data 需要申明儒将,static member function的調用可以通過兩種方式 1. 通過class name調用 2. 通過object 調用
通過static來實現(xiàn)單例模式栗子
class A{
public:
static A& getInstance() {
static A instance;
return instance;
};
void setup();
private:
A();
A(const A& other);
};
A::getInstance().setup();
cout
在c++源碼中發(fā)現(xiàn)吏祸,在ostream中對各種常見的類型做了重載,正是因為如此钩蚊,cout才可以接受那么多種類型并能打印出來class template 和 function template
之后模板的課程里會詳細講解