Stack
class Complex { ... };
...
Complex c3(1,2);
void main()
{
Complex c1(1,2);
static Complex c2(1,2);
Complex* p = new Complex(3); //heap
}
Stack栈:是存在于魔偶作用域的一块内存空间,函数本身会形成一个stack,存放接收的参数和返回地址以及local object。c1所用的空间来自stack。器生命在作用域之内有效,会自动清理,析构函数自动调用。
static object,生命在作用域结束之后仍然存在,析构函数在整个程序结束时调用。
golbal object:在程序结束时调用析构函数。
Heap
Heap堆:是指有操作系统提供的一块全局内存空间,可以通过动态分配来获取。p所指向的空间来之heap。
new
new:先分配memory,在调用构造函数
COmplex* pc = new Complex(1,2);
- void*mem = operator new(sizeof(Complex)); 其内部调用malloc()
- pc = static_cast<Complex*>(mem); 进行了一个转型
- pc->Complex::Complex(1,2); 调用构造函数,构造函数的全名:Complex::Complex(pc,1,2);pc是个隐藏的参数,通过this指针指向。
delete
delete:先调用析构函数,再释放内存
String* ps = new String("Hello");
...
delete ps;
1.String::~String(ps); 编译器给的析构函数时没有做什么事情的,对之前自己写的String类中,析构函数将String类中动态分配的内存释放掉。
2.operator delete(ps); 其内部调用free(ps),把字符串本身free,其中只有一个指针。
VC中内存分配
用VC的调试模式可以看到new分配的内存地址。new一个变量之后,除了得到本身的大小,还会得到前面32个后面4个以及前后各一个cock(4个字节),VC中每一块都是16的倍数,如果总和不够,还要填补一些空间进去。多的时给释放的时候用的,在vc的非调试模式下没有前后32+4的字节空间只有前后的cock,cock中记录了分配的空间大小,但是都是16的倍数,最后四位都是零,借以为来记录是还进来还是给出去,还进来是0,给出去是1.
new的时候用[],delete的时候也要用[],这是数组形式的。VC中数组在分配内存的时候,在存数据的前面会加4个字节,用来记录数组元素的个数。如果不搭配中括号[]会造成内存泄漏。上面delete中第二步删除的时候会看cock,将整个块删除。加上中括号,编译器会知道调用调用多次析构函数,将动态分配的内存删掉,如果不加中括号,只会调用析构函数一次,后面的部分就不会删掉。如果类的成员中没有指针,就不会存在这种情况,加不加中括号都会删掉。