刚看完了侯捷的《stl源码剖析》,很不错的一本书,打算对着vc的stl源码来验证一下。 而所有的C++对象第一步就是创建,我看了一下new中得代码,大概做个记录吧。理解的不深,纯做记录而已。
class CA { public: CA(void); ~CA(void); //void* operator new (size_t size); };
CA::CA(void) { } CA::~CA(void) { } //void* CA::operator new (size_t size) //{ // return malloc(size); // //}
这个类中我注掉的代码就是重载了该类的new 运算符的实现, 去掉注销的代码是直接可以运行的。 测试用的main函数如下:
#include "A.h" int main() { CA* a = new CA(); }
当编辑器在编译这个CA* a = new CA();语句时, 会先去调用new函数,如过类中没有自己定义的new函数,会去调用在<new>中得实现,该实现中是使用malloc来分配内存的,有一些异常处理的代码。在调用完new分配好内存后,就调用 CA类的构造函数来对数据进行初始化。这个流程在《深入浅出C++对象模型》中有讲的,刚翻了一下这本书。通过汇编代码,也可以验证这个流程
CA* a = new CA(); 004114ED push 1 // 因为 CA为空,所以传递给new的size是1 004114EF call operator new (4111EAh) //调用new函数 004114F4 add esp,4 004114F7 mov dword ptr [ebp-0E0h],eax 004114FD mov dword ptr [ebp-4],0 00411504 cmp dword ptr [ebp-0E0h],0 0041150B je main+70h (411520h) //如果内存非配不成功,跳转 0041150D mov ecx,dword ptr [ebp-0E0h] 00411513 call CA::CA (411014h) //内存分配好了, 然后调用 构造函数来 初始化对象 00411518 mov dword ptr [ebp-0F4h],eax // 将结果(指针值)放到一个内存里 0041151E jmp main+7Ah (41152Ah) 00411520 mov dword ptr [ebp-0F4h],0 //将 指针a 赋 0 值,表示分配未成功 0041152A mov eax,dword ptr [ebp-0F4h] //eax是 new CA(); 的返回值
这个流程比较简单清晰,但是以前不知道的。 当时在看哪个《深入浅出C++对象模型》时,看了, 也忘了, 所以觉得有必要记录一下。
有了new的基础,以后再好好看看VC中stl的源码的其他部分吧。 刚还捎带看了一眼malloc的代码,系统内部维护了一个列表_CrtMemBlockHeader * pHead;
这个结构没有看到定义,但是在运行时是可以看见的, 用vs看。