1. Object Based(基于对象) vs. Object Oriented(面向对象)
Object Based: 面对的是单一class的设计;
Object Oriented:面对的是多重classes的设计,class 和 class 之间的关系。
classes 的两个经典分类:
- class without pointer members -- complex
- class with pointer members -- string
2. 设计 string
2.1 防卫式声明
2.2 Big Three
若类内有指针成员,则一定要重写 拷贝构造函数,赋值构造函数和析构函数,即Big Three,执行深拷贝操作。编译器默认生成的 拷贝构造函数和赋值构造函数 只会进行浅拷贝!
由于未能确定string对象的大小,因此类内提供一个指针成员,指向动态内存。
2.3 ctor 和 dtor
注意!在析构函数中,调用 delete [] m_data; 释放内存。
在右下角的函数应用中,一旦离开作用域 {} , s1 和 s2 自动调用析构函数释放内存。由于 p 是动态分配的内存,其生命周期在整个程序运行周期内。p 要到程序结束运行后,由系统自动回收泄露的内存。
2.4 copy ctor 和 copy op=
拷贝构造函数
拷贝赋值函数
分3个步骤:
- 释放源对象动态内存;
- 重新分配动态内存空间;
- 拷贝动态内存中的内容;
其中,检测自我赋值有2层用意。
- 提高效率;
- 防止错误调用。其原因如下图所示,
2.5 符号重载函数
注意:返回值为 ostream& 类型。
2.6 new:先分配 memory,再调用ctor
使用 new 执行动态内存分配时,编译器执行如下3步操作。
2.7 delete: 先调用 dtor,再释放 memory
编译器执行2步删除操作。
第1步:?
第2步:?
2.8 动态分配所得的内存块 —— 以VC编译器为例
Debug 模式和 Release 模式创建一个对象耗费的内存大小不一样。如下图所示(4byte/框)
粉红色:cookie。指示了内存的大小,16进制。00 00 00 40 表示 4x16 字节。末位 1 是标志位,标识系统分配出内存给程序使用。
灰色:debug 模式下耗费的内存,共 32+4 byte。
绿色:对象的数据成员占用内存。 complex 为2个 double 变量,8 byte;string 为1个指针变量,4 byte。
青色:padding,用于将内存补全至 16 字节的倍数。
2.9 动态分配的 array —— 以VC编译器为例
array new 一定要搭配 array delete。养成良好的编程习惯。
array new —— new []
array delete —— delete []
Complex* p = new Complex[3]; 创建了一块数组,数组中存放3个 Complex 对象。
其内存计算方法和 2.8 节基本一样的,唯一区别在于多分配了4 byte 用于记录对象的数量。
若使用 array new 之后没有搭配 array delete,对于 string 类型的数组,对造成第2和第3个对象的内存泄露。而对于 Complex 类型的数组,并不会造成内存泄漏。
养成良好的编程习惯 —— 使用 array new 之后一定要搭配 array delete。