一:关于 string 类的实现过程中所涉及的三大函数:拷贝构造函数、拷贝赋值函数、析构函数
以下为类体部分:
class String { public: String(const char* cstr=0); String(const String& str); String& operator=(const String& str); ~String(); char* get_c_str() const { return m_data; } private: char* m_data; };
接下来是关于string类中构造函数、拷贝构造函数、拷贝赋值函数以及析构函数的具体定义,注意将以上函数写成 inline 函数:
(1)string 类中构造函数的定义:
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‘; } }
(2)拷贝构造函数的定义:
inline String::String(const String& str) { m_data = new char[ strlen(str.m_data) + 1 ]; strcpy(m_data, str.m_data); }
(3)拷贝赋值函数的定义:
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; }
(4)析构函数:
inline String::~String(){ delete[] m_data; }
二:Stack栈,Heap堆
Stack,是存在于某作用域的一块内存空间。例如:当调用函数时,函数本身即会形成一块栈用来存放其所接收的参数以及返回地址。在函数体内声明的任何变量,其所使用的内存块均取自stack。
Heap,由操作系统提供的一块global内存空间,程序可动态分配,从中获得某个区块。
例子:
class Complex {...} ... { Complex c1(1,2); Complex* p = new Complex(3); }
其中,c1 所占用的空间就来自于 stack,而 Complex(3)是个临时对象,其所占用的空间是以 new 自 heap 动态分配而得,并由 p 指向。
三、生命周期
(1)stack object 的生命周期
class complex {...}; ... { Complex c1(1,2); }
c1是stack object,其生命在作用域结束之际结束。这种作用域内的 object ,又称为 auto object,因为它会被自动清理。
(2)static local objects 的生命周期
class Complex { ... }; ... { static Complex c2(1,2); }
c2 是 static object, 其生命在作用域结束之后仍然存在,直到整个程序结束。
(3)global objects 的生命周期
class Complex { ... }; ... Complex c3(1,2); int main() { ... }
c3 是 global object,其申明在整个程序结束之后才结束,可视为一种 static object,其作用域是整个程序。
(4)heap objects 的生命周期
class Complex { ... }; ... { Complex* p=new Complex; ... delete p; }
四、new 和 delete
new :先分配内存,再调用构造函数
delete:先调用析构函数,再释放内存
五、关于 static
调用 static函数的方式有两种:
(1)通过 object 调用;
(2)通过 class name 调用