Classes 根据是否包含指针成员(指向动态内存(堆内存))可以分为:
Class without pointer member(s): complex
class complex{public: complex (double r = 0, double i = 0): re (r), im (i) { } complex& operator += (const complex&); complex& operator -= (const complex&); complex& operator *= (const complex&); complex& operator /= (const complex&); double real () const { return re; } double imag () const { return im; }private: double re, im;};
Class with pointer member(s): string
class String{public: String(const char* cstr=0); String(const String& str); String& operator=(const String& str); String::~String(){ delete[] m_data;} char* get_c_str() const { return m_data; }private: char* m_data;};
自然,对于包含有指针并使用了动态内存的类具有更高的复杂性,不能使用编译器默认提供的拷贝构造函数、拷贝赋值和析构函数,需要程序员自己重写。
对于类的对象自然也可以是栈对象,也可以是堆对象。
{ String s1("hello"); // 栈对象}// 当作用域结束时,自动调用~String()String *ps = new String("hello");delete ps;编译器自动转化为以下操作:String::~String(); //先调用析构函数,将对象中指针变量指向的空间释放掉operator delete(ps); //然后再释放自己所占的堆空间,底层调用的是C的free(ps)
对于包括有指针(指向堆内存)的堆对象,相当于使用了双重堆内存。
new的流程:
String *ps = new String("Hello");
编译器自动转化为以下操作:
String::~String(); // 先调用析构函数,将对象中指针变量指向的空间释放掉operator delete(ps); // 然后再释放自己所占的堆空间,底层调用的是C的free(ps)
![485368c173f18cc7694971bd22b6f456.png](https://i-blog.csdnimg.cn/blog_migrate/2db0f66c049e41f7d93d931067700999.jpeg)
指针ps位于栈上(&ps),其值是一个堆内存地址。
调用构造函数String("Hello"),m_data指向"Hello":
![c61ddcc25939b9aa3dbcc212552c1b61.png](https://i-blog.csdnimg.cn/blog_migrate/0fa5e512dd81937657accf3ed559ff4e.jpeg)
delete流程:
delete ps; // 手动释放
编译器自动转化为以下操作:
String::~String(); // 先调用析构函数,将对象中指针变量指向的空间释放掉operator delete(ps); // 然后再释放自己所占的堆空间,底层调用的是C的free(ps)
![b1856f502c1ddea5301746590d0ad3c7.png](https://i-blog.csdnimg.cn/blog_migrate/6f0644b8517e7d43ba17a6ddcd9e2f9a.jpeg)
先~String();,然后:delete(ps);
![1151489919bc06088c0e452e42c6b42e.png](https://i-blog.csdnimg.cn/blog_migrate/b6bcdc59222e578b9b81220172e1dad4.jpeg)
arrary new:
![b9547ac658c7ae01961d1f148bda0744.png](https://i-blog.csdnimg.cn/blog_migrate/e1ab3851b7dc12184d9f026cb29e7cb6.jpeg)
delete p:
![17cb4fe2871c4679edaf8b894893bd4c.png](https://i-blog.csdnimg.cn/blog_migrate/6845b6b74bb9c96ceca15352fc87188e.jpeg)
先~String(); 左边的一块堆内存释放掉了。
然后 delete(p); 右边的一块堆内存只释放掉了第一部分。
arrary delete: delete[] p :
![e0265989c7c655cc77e838ce02a53cb2.png](https://i-blog.csdnimg.cn/blog_migrate/ae96a3051e9d8115d08c841620e93d86.jpeg)
先~String(); 左边的一块堆内存释放掉了。
然后 delete[] (p); 其中的[]就是告诉编译器,需要释放的是多份。
ref : C++面向对象高级编程(侯捷)
https://www.bilibili.com/video/BV14s411E772
-End-