一、栈(Stack)&堆(Heap)
栈是存在于某作用域的一块内存空间(memory space)。栈在函数本体内声明的任何变量,其所使用的内存块都取自上述stack。
堆是由操作系统提供的一块global内存空间,程序可动态分配从某中获得若干区块。
class Complex{...}; ... { Complex c1(1,2); Complex* p = new Complex(3); }离开作用域,c1会自动释放,Complex(3)则需要手动delete
class Complex{...}; ... { Complex c1(1,2); }c1是stack object,其生命在作用域结束之际结束(自动调用析构函数),因为会被“自动”清理,又称auto object。
class Complex{...}; ... { static Complex c2(1,2); }c2是static object ,其生命在作用域结束之后仍存在,直到整个程序结束。
class Complex{...}; ... Complex c3(1,2); { ... }c3是globa object,其生命在整个程序结束之后才结束。可以视为一种static object,作用域是整个程序。
class Complex{...}; ... { Complex* p = new Complex(3); }以上会出现内存泄漏,因为当作用域结束,p所指的heap object仍然存在,但指针p的生命却结束了,作用域之外再也看不到p(也就没机会delete p)
正确写法如下
class Complex{...}; ... { Complex* p = new Complex(3); ... delete p; }二、内存动态分配
1, new:先分配memory(内存),再调用ctor(构造函数)
例如:
Complex* pc = new Complex(1,2);编译器会转化为
Complex *pc; void* mem = operator new( sizeof(Complex) ); //分配内存 pc = static_cast<Complex*>(mem); //转型 pc->Complex::Complex(1,2); //构造函数转化后的new内部会调用malloc(n)来分配内存
2.delete:先调用dtor(析构函数),再释放memory(内存)
例如:
Complex* pc = new Complex(1,2); ... delete pc;编译器会转化为:
Complex::~Complex(pc); //析构函数 operator delete(pc); //释放内存转化后的delete内部会调用free(pc)来释放内存
三、虚函数与多态
class Shape{ public: int objectID() const; //non—virtual virtual void error(const std:string& msg); //impure virtual virtual void draw() const = 0; //pure virtual ... };1,普通函数:不建议子类重写。
2,虚函数:可以被重新定义。
3,纯虚函数:一定要override。
4,vptr&vtable:vptr是类内存布局第一个成员,指向虚函数表vtable。