1、首先解释new关键字的作用
①在堆中开辟指定数据类型的空间
②调用指定数据类型的构造函数,创建对象
③返回创建的对象
int* pn=new int;// new与delete搭配使用
这种写法:pn为栈上的一个指针,指向堆上所对应的内存块。
int num;
int* pt=#
这种写法:指针pt以及变量num都在栈上。
2、何时用堆、何时用栈
一般情况下,自带数据类型int、容器等都声明在栈上(因为这些数据类型所占用内存大小是确定的,且较小)。在Windows下,栈是向低地址扩展数据结构。在栈上创建变量,优点是由操作系统自动分配与回收,效率高,缺点是分配的内存有限,不同的操作系统栈的内存不同,一般为2M或几M等。
而自定义数据类型struct、class等都new在堆上(这些所占用内存大小不确定,且较大,需要在程序运行的时候动态为其分配内存)。堆是向高地址扩展数据结构,是不连续内存区域。在堆上创建,由程序员malloc、new、free、delete,缺点是效率较栈低一些,优点是堆上有2G甚至更大的空间。只有调用到delete时才会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏。
int* t1=new int(1);
cout << "栈上指针所占内存大小:" << sizeof(t1) << endl;// 4
long long* t2 = new long long(1);
cout << "栈上指针所占内存大小:" << sizeof(t2) << endl;// 4
指针变量占用的内存空间大小根据所使用的操作系统及编译环境而定,指针类型占用的字节数是不同的。**32位平台上是4个字节,在64位平台上是8个字节。**这时如果声明一个8byte的指针指向堆中4byte的int类型,相当于买了一个装10L水的瓶子,每次只用来装10ml的水,得不偿失。
总结:当需要的内存很少,且确定需要多少内存时,用栈。当在运行时才知道需要多少内存时,用堆(new)。
3、生长方向:
栈的生长方向是向下生长,即由内存高地址向低地址生长。
堆的生长方向是向上生长,由内存的低地址向高地址生长。
堆和栈之间由一层临界区,大小可以进行修改,如果栈的空间到达临界区,则会提示stack overflow。